blob: bdeec6fce99559b581236669ee4140ed738fe97c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.netbeans.modules.payara.common;
import org.netbeans.modules.payara.tooling.admin.CommandRedeploy;
import org.netbeans.modules.payara.tooling.admin.CommandRestartDAS;
import org.netbeans.modules.payara.tooling.admin.CommandUndeploy;
import org.netbeans.modules.payara.tooling.admin.CommandDeploy;
import org.netbeans.modules.payara.tooling.admin.CommandDisable;
import org.netbeans.modules.payara.tooling.admin.CommandSetProperty;
import org.netbeans.modules.payara.tooling.admin.ResultMap;
import org.netbeans.modules.payara.tooling.admin.CommandGetProperty;
import org.netbeans.modules.payara.tooling.admin.Command;
import org.netbeans.modules.payara.tooling.admin.CommandEnable;
import org.netbeans.modules.payara.tooling.admin.ServerAdmin;
import org.netbeans.modules.payara.tooling.admin.ResultString;
import org.netbeans.modules.payara.tooling.admin.CommandListComponents;
import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.event.ChangeListener;
import org.netbeans.modules.payara.tooling.PayaraIdeException;
import org.netbeans.modules.payara.tooling.PayaraStatus;
import static org.netbeans.modules.payara.tooling.PayaraStatus.OFFLINE;
import static org.netbeans.modules.payara.tooling.PayaraStatus.SHUTDOWN;
import static org.netbeans.modules.payara.tooling.PayaraStatus.STARTUP;
import org.netbeans.modules.payara.tooling.TaskEvent;
import org.netbeans.modules.payara.tooling.TaskState;
import org.netbeans.modules.payara.tooling.TaskStateListener;
import org.netbeans.modules.payara.tooling.utils.Utils;
import org.netbeans.modules.payara.common.nodes.actions.RefreshModulesCookie;
import org.netbeans.modules.payara.common.utils.Util;
import org.netbeans.modules.payara.spi.AppDesc;
import org.netbeans.modules.payara.spi.CommandFactory;
import static org.netbeans.modules.payara.spi.PayaraModule.HOSTNAME_ATTR;
import static org.netbeans.modules.payara.spi.PayaraModule.PROPERTIES_FETCH_TIMEOUT;
import org.netbeans.modules.payara.spi.PayaraModule.ServerState;
import org.netbeans.modules.payara.spi.Recognizer;
import org.netbeans.modules.payara.spi.RecognizerCookie;
import org.netbeans.modules.payara.spi.ResourceDesc;
import org.netbeans.modules.payara.spi.VMIntrospector;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.util.ChangeSupport;
import org.openide.util.NbBundle;
import org.openide.util.RequestProcessor;
import org.openide.util.lookup.Lookups;
import org.netbeans.modules.payara.spi.PayaraModule;
import org.netbeans.modules.payara.spi.PayaraModule3;
import org.netbeans.modules.payara.tooling.data.PayaraServerStatus;
import org.netbeans.modules.payara.tooling.data.PayaraVersion;
/**
* Payara server support API.
* <p/>
* @author Peter Williams, Tomas Kraus
*/
public class CommonServerSupport
implements PayaraModule3, RefreshModulesCookie {
////////////////////////////////////////////////////////////////////////////
// Inner classes //
////////////////////////////////////////////////////////////////////////////
/**
* Task state listener watching __locations command execution.
*/
private static class LocationsTaskStateListener
implements TaskStateListener {
/** Payara server support object instance. */
final CommonServerSupport css;
/**
* Creates an instance of task state listener watching __locations
* command execution.
* <p/>
* @param css Payara server support object instance.
*/
LocationsTaskStateListener(CommonServerSupport css) {
this.css = css;
}
private String adminCommandFailedMsg(String resName, String[] args) {
String serverName = args[0];
String command = args[1];
String exMessage = args.length > 2 ? args[2] : null;
return args.length > 2
? NbBundle.getMessage(CommonServerSupport.class, resName,
args[0], args[1], args[2])
: NbBundle.getMessage(CommonServerSupport.class, resName,
args[0], args[1]);
}
/**
* Callback to notify about Payara __locations command execution
* state change.
* <p/>
* <code>String</codce> arguments passed to state listener
* from runner:<ul>
* <li><code>args[0]</code> server name</li>
* <li><code>args[1]</code> administration command</li>
* <li><code>args[2]</code> exception message</li>
* <li><code>args[3]</code> display message in GUI</li></ul>
* <p/>
* @param newState New command execution state.
* @param event Event related to execution state change.
* @param args <code>String</codce> arguments passed to state
* listener.
*/
@Override
public void operationStateChanged(
TaskState newState, TaskEvent event,
String[] args) {
// Server name and command are mandatory.
if (args.length > 1) {
String exMessage = args.length > 2 ? args[2] : null;
boolean display = args.length > 3
? Boolean.parseBoolean(args[3]) : false;
if (display) {
long lastDisplayed = css.getLatestWarningDisplayTime();
long currentTime = System.currentTimeMillis();
if (TaskState.FAILED == newState
&& currentTime - lastDisplayed > 5000) {
String message;
switch (event) {
case EXCEPTION:
if (exMessage != null
&& exMessage.length() > 0) {
message = adminCommandFailedMsg(
"MSG_ADMIN_EXCEPTION", args);
} else {
message = adminCommandFailedMsg(
"MSG_ADMIN_FAILED", args);
}
break;
case AUTH_FAILED: case AUTH_FAILED_HTTP:
message = adminCommandFailedMsg(
"MSG_ADMIN_AUTH_FAILED", args);
break;
default:
message = adminCommandFailedMsg(
"MSG_ADMIN_FAILED", args);
}
displayPopUpMessage(css, message);
}
}
}
}
}
class StartOperationStateListener implements TaskStateListener {
private ServerState endState;
StartOperationStateListener(ServerState endState) {
this.endState = endState;
}
@Override
public void operationStateChanged(TaskState newState, TaskEvent event,
String... args) {
if(newState == TaskState.RUNNING) {
setServerState(ServerState.STARTING);
} else if(newState == TaskState.COMPLETED) {
startedByIde = isRemote
? false : PayaraState.isOnline(instance);
setServerState(endState);
} else if(newState == TaskState.FAILED) {
setServerState(ServerState.STOPPED);
// Open a warning dialog here...
NotifyDescriptor nd = new NotifyDescriptor.Message(Utils.concatenate(args));
DialogDisplayer.getDefault().notifyLater(nd);
}
}
}
class StopOperationStateListener implements TaskStateListener {
@Override
public void operationStateChanged(
TaskState newState, TaskEvent event, String... args) {
if (newState == TaskState.RUNNING) {
setServerState(ServerState.STOPPING);
} else if (newState == TaskState.COMPLETED) {
setServerState(ServerState.STOPPED);
} else if (newState == TaskState.FAILED) {
// Possible bug: What if server was started in other mode
// than RUNNING.
setServerState(ServerState.RUNNING);
}
}
};
class KillOperationStateListener implements TaskStateListener {
@Override
public void operationStateChanged(final TaskState newState,
final TaskEvent event, final String... args) {
if (newState == TaskState.RUNNING) {
setServerState(ServerState.STOPPING);
} else if (newState == TaskState.COMPLETED) {
setServerState(ServerState.STOPPED);
} else if (newState == TaskState.FAILED) {
// Registered process has already finished.
if (event == TaskEvent.PROCESS_NOT_RUNNING) {
setServerState(ServerState.STOPPED);
}
// Otherwise do nothing for TaskEvent.PROCESS_NOT_EXISTS.
}
}
};
////////////////////////////////////////////////////////////////////////////
// Class attributes //
////////////////////////////////////////////////////////////////////////////
/** Local logger. */
private static final Logger LOGGER
= PayaraLogger.get(CommonServerSupport.class);
/** Local host name (DNS). */
private static final String LOCALHOST = "localhost";
/** String to return for failed {@see getHttpHostFromServer()} search. */
private static final String FAILED_HTTP_HOST = LOCALHOST + "FAIL";
////////////////////////////////////////////////////////////////////////////
// Static methods //
////////////////////////////////////////////////////////////////////////////
/**
* Display pop up window with given message.
* <p/>
* Method is thread safe.
* <p/>
* @param css Payara server support object.
* @param message Message to be displayed.
*/
public static void displayPopUpMessage(final CommonServerSupport css,
final String message) {
synchronized (css) {
NotifyDescriptor nd = new NotifyDescriptor.Message(message);
DialogDisplayer.getDefault().notifyLater(nd);
css.setLatestWarningDisplayTime(System.currentTimeMillis());
LOGGER.log(Level.INFO, message);
}
}
////////////////////////////////////////////////////////////////////////////
// Instance attributes //
////////////////////////////////////////////////////////////////////////////
/** Managed Payara instance. */
private final PayaraInstance instance;
private volatile ServerState serverState = ServerState.UNKNOWN;
private final Object stateMonitor = new Object();
private ChangeSupport changeSupport = new ChangeSupport(this);
private FileObject instanceFO;
private volatile boolean startedByIde = false;
/** Cache local/remote test for instance. */
private transient boolean isRemote = false;
// prevent j2eeserver from stopping an authenticated domain that
// the IDE did not start.
private boolean stopDisabled = false;
private Process localStartProcess;
/** Last executed start task. */
private volatile FutureTask<TaskState> startTask;
////////////////////////////////////////////////////////////////////////////
// Constructors //
////////////////////////////////////////////////////////////////////////////
CommonServerSupport(PayaraInstance instance) {
this.instance = instance;
this.isRemote = instance.isRemote();
// !PW FIXME temporary patch for JavaONE 2008 to make it easier
// to persist per-instance property changes made by the user.
instanceFO = getInstanceFileObject();
startTask = null;
}
/**
* Get <code>PayaraInstance</code> object associated with this object.
* <p/>
* @return <code>PayaraInstance</code> object associated with this object.
*/
@Override
public PayaraInstance getInstance() {
return this.instance;
}
private FileObject getInstanceFileObject() {
FileObject dir = FileUtil.getConfigFile(
instance.getInstanceProvider().getInstancesDirFirstName());
if(dir != null) {
String instanceFN = instance
.getProperty(PayaraInstance.INSTANCE_FO_ATTR);
if(instanceFN != null) {
return dir.getFileObject(instanceFN);
}
}
return null;
}
@Override
public String getPassword() {
return instance.getPassword();
}
/** @deprecated Use in <code>PayaraInstance</code> context. */
@Deprecated
public String getInstallRoot() {
return instance.getInstallRoot();
}
/** @deprecated Use in <code>PayaraInstance</code> context. */
@Deprecated
public String getPayaraRoot() {
return instance.getPayaraRoot();
}
/** @deprecated Use in <code>PayaraInstance</code> context. */
@Deprecated
public String getDisplayName() {
return instance.getDisplayName();
}
/** @deprecated Use in <code>PayaraInstance</code> context. */
@Deprecated
public String getDeployerUri() {
return instance.getDeployerUri();
}
/** @deprecated Use in <code>PayaraInstance</code> context. */
@Deprecated
public String getUserName() {
return instance.getUserName();
}
/** @deprecated Use in <code>PayaraInstance</code> context. */
@Deprecated
public String getAdminPort() {
return instance.getHttpAdminPort();
}
/** @deprecated Use in <code>PayaraInstance</code> context. */
@Deprecated
public String getHttpPort() {
return instance.getHttpPort();
}
/** @deprecated Use in <code>PayaraInstance</code> context. */
@Deprecated
public int getHttpPortNumber() {
return instance.getPort();
}
/** @deprecated Use in <code>PayaraInstance</code> context. */
@Deprecated
public int getAdminPortNumber() {
return instance.getAdminPort();
}
/** @deprecated Use in <code>PayaraInstance</code> context. */
@Deprecated
public String getHostName() {
return instance.getProperty(HOSTNAME_ATTR);
}
/** @deprecated Use in <code>PayaraInstance</code> context. */
@Deprecated
public String getDomainsRoot() {
return instance.getDomainsRoot();
}
/** @deprecated Use in <code>PayaraInstance</code> context. */
@Deprecated
public String getDomainName() {
return instance.getDomainName();
}
public void setServerState(final ServerState newState) {
// Synchronized on private monitor to serialize changes in state.
// Storage of serverState is volatile to facilitate readability of
// current state regardless of lock status.
boolean fireChange = false;
synchronized (stateMonitor) {
if(serverState != newState) {
serverState = newState;
fireChange = true;
}
}
if(fireChange) {
changeSupport.fireChange();
}
}
boolean isStartedByIde() {
return startedByIde;
}
// ------------------------------------------------------------------------
// PayaraModule interface implementation
// ------------------------------------------------------------------------
@Override
public Map<String, String> getInstanceProperties() {
// force the domains conversion
getDomainsRoot();
return Collections.unmodifiableMap(instance.getProperties());
}
@Override
public PayaraInstanceProvider getInstanceProvider() {
return instance.getInstanceProvider();
}
@Override
public boolean isRemote() {
return isRemote;
}
private static final RequestProcessor RP = new RequestProcessor("CommonServerSupport - start/stop/refresh",5); // NOI18N
@Override
public Future<TaskState> startServer(
final TaskStateListener stateListener, ServerState endState) {
LOGGER.log(Level.FINEST,
"CSS.startServer called on thread \"{0}\"",
Thread.currentThread().getName());
TaskStateListener startServerListener = new StartOperationStateListener(endState);
VMIntrospector vmi = Lookups.forPath(Util.PF_LOOKUP_PATH).lookup(VMIntrospector.class);
FutureTask<TaskState> task = new FutureTask<TaskState>(
new StartTask(this, getRecognizers(), vmi,
endState == ServerState.STOPPED_JVM_PROFILER ? new String[]{""} : null,
startServerListener, stateListener));
startTask = task;
RP.post(task);
return task;
}
private List<Recognizer> getRecognizers() {
List<Recognizer> recognizers;
Collection<? extends RecognizerCookie> cookies =
instance.localLookup().lookupAll(RecognizerCookie.class);
if(!cookies.isEmpty()) {
recognizers = new LinkedList<Recognizer>();
for(RecognizerCookie cookie: cookies) {
recognizers.addAll(cookie.getRecognizers());
}
recognizers = Collections.unmodifiableList(recognizers);
} else {
recognizers = Collections.emptyList();
}
return recognizers;
}
@Override
public Future<TaskState> stopServer(final TaskStateListener stateListener) {
LOGGER.log(Level.FINEST, "CSS.stopServer called on thread \"{0}\"", Thread.currentThread().getName()); // NOI18N
TaskStateListener stopServerListener = new StopOperationStateListener();
FutureTask<TaskState> task;
if (!isRemote() || !Util.isDefaultOrServerTarget(instance.getProperties())) {
if (getServerState() == ServerState.STOPPED_JVM_PROFILER) {
task = new FutureTask<TaskState>(
new StopProfilingTask(this, stateListener));
} else {
task = new FutureTask<TaskState>(
new StopTask(this, stopServerListener, stateListener));
}
// prevent j2eeserver from stopping a server it did not start.
} else {
task = new FutureTask<TaskState>(
new NoopTask(this,stopServerListener,stateListener));
}
if (stopDisabled) {
stopServerListener.operationStateChanged(
TaskState.COMPLETED, TaskEvent.CMD_COMPLETED, "");
if (null != stateListener) {
stateListener.operationStateChanged(
TaskState.COMPLETED, TaskEvent.CMD_COMPLETED, "");
}
return task;
}
RP.post(task);
return task;
}
/** Delay between checking task state while waiting it
* to die [ms]. */
private static final int WAIT_TASK_TO_DIE_SLEEP = 300;
/** Maximum time to wait for task to die [ms]. */
private static final int WAIT_TASK_TO_DIE_MAX = 3000;
/**
* Terminates local Payara server process when started from UI.
* <p/>
* @param stateListener External state listener to register.
* @return Asynchronous Payara server termination task when
*/
@Override
@SuppressWarnings("SleepWhileInLoop")
public Future<TaskState> killServer(final TaskStateListener stateListener) {
TaskStateListener killServerListener = new KillOperationStateListener();
FutureTask<TaskState> task;
boolean isStateListener = stateListener != null;
if (!isRemote() && instance.getProcess() != null) {
FutureTask<TaskState> stTask = this.startTask;
// Stop running StartTask and wait for it to die.
if (stTask != null && !stTask.isDone()) {
stTask.cancel(true);
long startTime = System.currentTimeMillis();
while(!stTask.isDone()
&& System.currentTimeMillis() - startTime
< WAIT_TASK_TO_DIE_MAX) {
try {
Thread.sleep(WAIT_TASK_TO_DIE_SLEEP);
} catch (InterruptedException ex) {
LOGGER.log(Level.INFO,
"Caught InterruptedException while waiting for "
+ "{0} start task to die.",
instance.getName());
}
}
if (!stTask.isDone()) {
LOGGER.log(Level.INFO,
"Start task for {0} did not finish within {1} ms.",
new String[] {instance.getName(),
Integer.toString(WAIT_TASK_TO_DIE_MAX)});
}
}
TaskStateListener[] listeners
= new TaskStateListener[isStateListener ? 2 : 1];
listeners[0] = killServerListener;
if (isStateListener) {
listeners[1] = stateListener;
}
task = new FutureTask<TaskState>(new KillTask(instance, listeners));
} else {
task = new FutureTask<TaskState>(
new NoopTask(this, null, stateListener));
}
RP.post(task);
return task;
}
@Override
public Future<TaskState> restartServer(TaskStateListener stateListener) {
LOGGER.log(Level.FINEST,
"CSS.restartServer called on thread \"{0}\"",
Thread.currentThread().getName());
FutureTask<TaskState> task = new FutureTask<TaskState>(
new RestartTask(this, stateListener));
RP.post(task);
return task;
}
/**
* Sends restart-domain command to server (asynchronous)
*
*/
public Future<ResultString> restartServer(final int debugPort,
boolean debug, TaskStateListener[] listeners) {
if (-1 == debugPort) {
Command command = new CommandRestartDAS(false);
return ServerAdmin.<ResultString>exec(
instance, command, null, listeners);
}
TaskState state = null;
try {
ResultMap<String, String> result
= CommandGetProperty.getProperties(instance,
"configs.config.server-config.java-config.debug-options");
if (result.getState() == TaskState.COMPLETED) {
Map<String, String> values = result.getValue();
if (values != null && !values.isEmpty()) {
String oldValue = values.get(
"configs.config.server-config.java-config.debug-options");
CommandSetProperty setCmd =
getCommandFactory().getSetPropertyCommand(
"configs.config.server-config.java-config.debug-options",
oldValue.replace("transport=dt_shmem", "transport=dt_socket").
replace("address=[^,]+", "address=" + debugPort));
try {
CommandSetProperty.setProperty(instance, setCmd);
debug = true;
} catch (PayaraIdeException gfie) {
debug = false;
LOGGER.log(Level.INFO, debugPort + "", gfie);
}
}
}
} catch (PayaraIdeException gfie) {
LOGGER.log(Level.INFO,
"Could not retrieve property from server.", gfie);
}
Command command = new CommandRestartDAS(debug);
return ServerAdmin.<ResultString>exec(
instance, command, null, listeners);
}
@Override
public Future<ResultString> deploy(final TaskStateListener stateListener,
final File application, final String name) {
return deploy(stateListener, application, name, null);
}
@Override
public Future<ResultString> deploy(final TaskStateListener stateListener,
final File application, final String name,
final String contextRoot) {
return deploy(stateListener, application, name, contextRoot, null);
}
@Override
public Future<ResultString> deploy(final TaskStateListener stateListener,
final File application, final String name, final String contextRoot,
final Map<String,String> properties) {
return deploy(stateListener, application, name, contextRoot, null, new File[0]);
}
@Override
public Future<ResultString> deploy(final TaskStateListener stateListener,
final File application, final String name, final String contextRoot,
final Map<String, String> properties, final File[] libraries) {
try {
return ServerAdmin.<ResultString>exec(instance, new CommandDeploy(
name, Util.computeTarget(instance.getProperties()),
application, contextRoot, properties, libraries,
instance.isHotDeployEnabled()
), null, new TaskStateListener[]{stateListener});
} finally {
refreshChildren();
}
}
@Override
public Future<ResultString> redeploy(
final TaskStateListener stateListener,
final String name, boolean resourcesChanged,
boolean metadataChanged, List<String> sourcesChanged) {
return redeploy(stateListener, name, null,
resourcesChanged, metadataChanged, sourcesChanged);
}
@Override
public Future<ResultString> redeploy(
final TaskStateListener stateListener,
final String name, final String contextRoot,
boolean resourcesChanged, boolean metadataChanged, List<String> sourcesChanged) {
return redeploy(stateListener, name, contextRoot, new File[0],
resourcesChanged, metadataChanged, sourcesChanged);
}
@Override
public Future<ResultString> redeploy(TaskStateListener stateListener,
String name, String contextRoot, File[] libraries,
boolean resourcesChanged, boolean metadataChanged, List<String> sourcesChanged) {
Map<String, String> properties = new HashMap<>();
String url = instance.getProperty(PayaraModule.URL_ATTR);
String sessionPreservationFlag = instance.getProperty(PayaraModule.SESSION_PRESERVATION_FLAG);
if (sessionPreservationFlag == null) {
// If there isn't a value stored for the instance, use the value of
// the command-line flag.
sessionPreservationFlag = System.getProperty(
"glassfish.session.preservation.enabled", "false");
}
if (Boolean.parseBoolean(sessionPreservationFlag)) {
properties.put("keepSessions", "true");
}
if (resourcesChanged) {
properties.put("preserveAppScopedResources", "true");
}
try {
return ServerAdmin.<ResultString>exec(instance, new CommandRedeploy(
name, Util.computeTarget(instance.getProperties()),
contextRoot, properties, libraries,
url != null && url.contains("deployer:pfv"),
instance.isHotDeployEnabled(),
metadataChanged, sourcesChanged
), stateListener);
} finally {
refreshChildren();
}
}
@Override
public Future<ResultString> undeploy(
final TaskStateListener stateListener, final String name) {
return ServerAdmin.<ResultString>exec(
instance, new CommandUndeploy(name, Util.computeTarget(
instance.getProperties())), null,
new TaskStateListener[]{stateListener});
}
@Override
public Future<ResultString> enable(
final TaskStateListener stateListener, final String name) {
return ServerAdmin.<ResultString>exec(instance, new CommandEnable(
name, Util.computeTarget(instance.getProperties())), null,
new TaskStateListener[] {stateListener});
}
@Override
public Future<ResultString> disable(
final TaskStateListener stateListener, final String name) {
return ServerAdmin.<ResultString>exec(instance, new CommandDisable(
name, Util.computeTarget(instance.getProperties())), null,
new TaskStateListener[] {stateListener});
}
@Override
public AppDesc [] getModuleList(String container) {
int total = 0;
Map<String, List<AppDesc>> appMap = getApplications(container);
Collection<List<AppDesc>> appLists = appMap.values();
for(List<AppDesc> appList: appLists) {
total += appList.size();
}
AppDesc [] result = new AppDesc[total];
int index = 0;
for(List<AppDesc> appList: appLists) {
for(AppDesc app: appList) {
result[index++] = app;
}
}
return result;
}
@Override
public Map<String, ResourceDesc> getResourcesMap(String type) {
Map<String, ResourceDesc> resourcesMap
= new HashMap<String, ResourceDesc>();
List<ResourceDesc> resourcesList
= ResourceDesc.getResources(instance, type);
for (ResourceDesc resource : resourcesList) {
resourcesMap.put(resource.getName(), resource);
}
return resourcesMap;
}
@Override
public ServerState getServerState() {
if (serverState == ServerState.UNKNOWN) {
RequestProcessor.Task task = refresh();
if (task != null) {
task.waitFinished();
}
}
return serverState;
}
@Override
public void addChangeListener(final ChangeListener listener) {
changeSupport.addChangeListener(listener);
}
@Override
public void removeChangeListener(final ChangeListener listener) {
changeSupport.removeChangeListener(listener);
}
@Override
public String setEnvironmentProperty(final String name, final String value,
final boolean overwrite) {
String result;
synchronized (instance.getProperties()) {
result = instance.getProperty(name);
if(result == null || overwrite == true) {
instance.putProperty(name, value);
setInstanceAttr(name, value);
result = value;
}
}
return result;
}
// ------------------------------------------------------------------------
// bookkeeping & impl managment, not exposed via interface.
// ------------------------------------------------------------------------
void setProperty(final String key, final String value) {
instance.putProperty(key, value);
}
void getProperty(String key) {
instance.getProperty(key);
}
boolean setInstanceAttr(String name, String value) {
boolean retVal = false;
if(instanceFO == null || !instanceFO.isValid()) {
instanceFO = getInstanceFileObject();
}
if(instanceFO != null && instanceFO.canWrite()) {
try {
Object currentValue = instanceFO.getAttribute(name);
if (null != currentValue && currentValue.equals(value)) {
// do nothing
} else {
instanceFO.setAttribute(name, value);
}
retVal = true;
} catch(IOException ex) {
LOGGER.log(Level.WARNING,
"Unable to save attribute " + name + " in " + instanceFO.getPath() + " for " + getDeployerUri(), ex); // NOI18N
}
} else {
if (null == instanceFO)
LOGGER.log(Level.WARNING,
"Unable to save attribute {0} for {1} in {3}. Instance file is writable? {2}",
new Object[]{name, getDeployerUri(), false, "null"}); // NOI18N
else
LOGGER.log(Level.WARNING,
"Unable to save attribute {0} for {1} in {3}. Instance file is writable? {2}",
new Object[]{name, getDeployerUri(), instanceFO.canWrite(), instanceFO.getPath()}); // NOI18N
}
return retVal;
}
void setFileObject(FileObject fo) {
instanceFO = fo;
}
public static boolean isRunning(final String host, final int port,
final String name, final int timeout) {
if(null == host)
return false;
try {
InetSocketAddress isa = new InetSocketAddress(host, port);
Socket socket = new Socket();
Logger.getLogger("payara-socket-connect-diagnostic").log(
Level.FINE, "Using socket.connect", new Exception());
socket.connect(isa, timeout);
socket.setSoTimeout(timeout);
try {
socket.close();
} catch (IOException ioe) {
LOGGER.log(
Level.INFO, "Socket closing failed: {0}",
ioe.getMessage());
}
return true;
} catch (java.net.ConnectException | java.net.SocketTimeoutException ex) {
return false;
} catch (IOException ioe) {
String message = NbBundle.getMessage(CommonServerSupport.class,
name == null || "".equals(name.trim())
? "MSG_FLAKEY_NETWORK" : "MSG_FLAKEY_NETWORK2",
host, Integer.toString(port), ioe.getLocalizedMessage());
NotifyDescriptor nd = new NotifyDescriptor.Message(message);
DialogDisplayer.getDefault().notifyLater(nd);
LOGGER.log(Level.INFO,
"Evidence of network flakiness: {0}", ioe.getMessage());
return false;
}
}
public static boolean isRunning(final String host, final int port,
final String name) {
return isRunning(host, port, name, 2000);
}
// ------------------------------------------------------------------------
// RefreshModulesCookie implementation (for refreshing server state)
// ------------------------------------------------------------------------
private final AtomicBoolean refreshRunning = new AtomicBoolean(false);
@Override
public final RequestProcessor.Task refresh() {
return refresh(null,null);
}
@Override
public RequestProcessor.Task refresh(String expected, String unexpected) {
if(refreshRunning.compareAndSet(false, true)) {
return RP.post(new Runnable() {
@Override
public void run() {
// Get current server status.
PayaraServerStatus status
= PayaraStatus.get(instance);
// Start monitoring of this Payara server instance
// when status is null and refresh status.
if (status == null) {
PayaraState.monitor(instance);
status = PayaraStatus.get(instance);
}
ServerState currentState = serverState;
switch(currentState) {
case UNKNOWN:
switch(status.getStatus()) {
case ONLINE:
setServerState(ServerState.RUNNING);
break;
case STARTUP:
setServerState(ServerState.STARTING);
break;
case SHUTDOWN:
setServerState(ServerState.STOPPING);
break;
case OFFLINE:
setServerState(ServerState.STOPPED);
}
break;
case STOPPED:
if (status.getStatus() == PayaraStatus.ONLINE) {
setServerState(ServerState.RUNNING);
}
break;
case RUNNING:
switch(status.getStatus()) {
case STARTUP:
setServerState(ServerState.STARTING);
break;
case SHUTDOWN:
setServerState(ServerState.STOPPING);
break;
case OFFLINE:
setServerState(ServerState.STOPPED);
}
break;
case STOPPED_JVM_PROFILER:
if (status.getStatus() == PayaraStatus.ONLINE) {
setServerState(ServerState.RUNNING);
}
}
refreshRunning.set(false);
}
});
} else {
return null;
}
}
void disableStop() {
stopDisabled = true;
}
void setLocalStartProcess(Process process) {
this.localStartProcess = process;
}
Process getLocalStartProcess() {
return localStartProcess;
}
void stopLocalStartProcess() {
localStartProcess.destroy();
localStartProcess = null;
}
@Override
public CommandFactory getCommandFactory() {
return instance.getInstanceProvider().getCommandFactory();
}
@Override
public String getResourcesXmlName() {
return org.netbeans.modules.payara.spi.Utils
.useGlassFishPrefix(getDeployerUri()) ?
"glassfish-resources" : "sun-resources"; // NOI18N
}
@Override
public boolean supportsRestartInDebug() {
return getDeployerUri().contains(PayaraInstanceProvider.EE6WC_DEPLOYER_FRAGMENT);
}
@Override
public boolean isRestfulLogAccessSupported() {
return getDeployerUri().contains(PayaraInstanceProvider.EE6WC_DEPLOYER_FRAGMENT);
}
@Override
public boolean isWritable() {
return (null == instanceFO) ? false : instanceFO.canWrite();
}
private long latestWarningDisplayTime = System.currentTimeMillis();
private long getLatestWarningDisplayTime() {
return latestWarningDisplayTime;
}
private void setLatestWarningDisplayTime(long currentTime) {
latestWarningDisplayTime = currentTime;
}
/**
* Update HTTP port value from server properties.
*/
void updateHttpPort() {
String target = Util.computeTarget(instance.getProperties());
String gpc;
if (Util.isDefaultOrServerTarget(instance.getProperties())) {
gpc = "*.server-config.*.http-listener-1.port";
setEnvironmentProperty(PayaraModule.HTTPHOST_ATTR,
instance.getProperty(PayaraModule.HOSTNAME_ATTR), true); // NOI18N
} else {
String server = getServerFromTarget(target);
String adminHost = instance.getProperty(PayaraModule.HOSTNAME_ATTR);
setEnvironmentProperty(PayaraModule.HTTPHOST_ATTR,
getHttpHostFromServer(server,adminHost), true);
gpc = "servers.server."+server+".system-property.HTTP_LISTENER_PORT.value";
}
try {
ResultMap<String, String> result = CommandGetProperty.getProperties(
instance, gpc, PayaraModule.PROPERTIES_FETCH_TIMEOUT);
boolean didSet = false;
if (result.getState() == TaskState.COMPLETED) {
Map<String, String> values = result.getValue();
for (Entry<String, String> entry : values.entrySet()) {
String val = entry.getValue();
try {
if (null != val && val.trim().length() > 0) {
Integer.parseInt(val);
setEnvironmentProperty(PayaraModule.HTTPPORT_ATTR, val, true);
didSet = true;
}
} catch (NumberFormatException nfe) {
LOGGER.log(Level.FINEST,
"Property value {0} was not a number", val);
}
}
}
if (!didSet && !Util.isDefaultOrServerTarget(instance.getProperties())) {
setEnvironmentProperty(PayaraModule.HTTPPORT_ATTR, "28080", true); // NOI18N
}
} catch (PayaraIdeException gfie) {
LOGGER.log(Level.INFO, "Could not get http port value.", gfie);
}
}
/**
* Sends list-applications command to server (synchronous)
*
* @param container
* @return String array of names of deployed applications.
*/
public Map<String, List<AppDesc>> getApplications(String container) {
Map<String, List<AppDesc>> result = Collections.emptyMap();
Map<String, List<String>> apps = Collections.emptyMap();
try {
ResultMap<String, List<String>> resultMap
= CommandListComponents.listComponents(instance,
Util.computeTarget(instance.getProperties()));
if (resultMap.getState() == TaskState.COMPLETED) {
apps = resultMap.getValue();
}
} catch (PayaraIdeException gfie) {
LOGGER.log(Level.INFO,
"Could not retrieve components server.", gfie);
}
if (null == apps || apps.isEmpty()) {
return result;
}
try {
ResultMap<String, String> appPropsResult = CommandGetProperty
.getProperties(instance, "applications.application.*");
if (appPropsResult.getState() == TaskState.COMPLETED) {
ResultMap<String, String> appRefResult
= CommandGetProperty.getProperties(
instance, "servers.server.*.application-ref.*");
if (appRefResult.getState() == TaskState.COMPLETED) {
result = processApplications(apps,
appPropsResult.getValue(),
appRefResult.getValue());
}
}
} catch (PayaraIdeException gfie) {
LOGGER.log(Level.INFO,
"Could not retrieve property from server.", gfie);
}
return result;
}
private Map<String, List<AppDesc>> processApplications(Map<String,
List<String>> appsList, Map<String, String> properties,
Map<String, String> refProperties){
Map<String, List<AppDesc>> result = new HashMap<String, List<AppDesc>>();
Iterator<String> appsItr = appsList.keySet().iterator();
while (appsItr.hasNext()) {
String engine = appsItr.next();
List<String> apps = appsList.get(engine);
for (int i = 0; i < apps.size(); i++) {
String name = apps.get(i).trim();
String appname = "applications.application." + name; // NOI18N
String contextKey = appname + ".context-root"; // NOI18N
String pathKey = appname + ".location"; // NOI18N
String contextRoot = properties.get(contextKey);
if (contextRoot == null) {
contextRoot = name;
}
if (contextRoot.startsWith("/")) { // NOI18N
contextRoot = contextRoot.substring(1);
}
String path = properties.get(pathKey);
if (path == null) {
path = "unknown"; //NOI18N
}
if (path.startsWith("file:")) { // NOI18N
path = path.substring(5);
path = (new File(path)).getAbsolutePath();
}
String enabledKey = "servers.server.server.application-ref."
+name+ ".enabled"; //NOI18N
// This needs to be more focused. Does it need to list
// of servers that are associated with the target?
for (String possibleKey : refProperties.keySet()) {
if (possibleKey.endsWith(".application-ref."
+ name + ".enabled")) { // NOI18N
enabledKey = possibleKey;
}
}
String enabledValue = refProperties.get(enabledKey);
if (null != enabledValue) {
boolean enabled = Boolean.parseBoolean(enabledValue);
List<AppDesc> appList = result.get(engine);
if(appList == null) {
appList = new ArrayList<AppDesc>();
result.put(engine, appList);
}
appList.add(new AppDesc(name, path, contextRoot, enabled));
}
}
}
return result;
}
/**
* Retrieve server name using target name from server properties.
* <p/>
* @param target Server target name.
* @return Name of server having this target.
*/
private String getServerFromTarget(String target) {
String retVal = target; // NOI18N
String gpc = "clusters.cluster."+target+".server-ref.*.ref";
try {
ResultMap<String, String> result = CommandGetProperty.getProperties(
instance, gpc, PROPERTIES_FETCH_TIMEOUT);
if (result.getState() == TaskState.COMPLETED) {
Map<String, String> values = result.getValue();
for (Entry<String, String> entry : values.entrySet()) {
String val = entry.getValue();
if (null != val && val.trim().length() > 0) {
retVal = val;
break;
}
}
}
} catch (PayaraIdeException gfie) {
LOGGER.log(Level.INFO, "Could not get server value from target.", gfie);
}
return retVal;
}
/**
* Retrieve HTTP host name for server from server properties.
* <p/>
* @param server Server name.
* @param nameOfLocalhost Local host DNS name.
* @return HTTP host name for server.
*/
private String getHttpHostFromServer(
String server, String nameOfLocalhost) {
String retVal = FAILED_HTTP_HOST;
String refVal = null;
String gpc = "servers.server."+server+".node-ref";
try {
ResultMap<String, String> result = CommandGetProperty.getProperties(
instance, gpc, PROPERTIES_FETCH_TIMEOUT);
if (result.getState() == TaskState.COMPLETED) {
for (Entry<String, String> entry
: result.getValue().entrySet()) {
String val = entry.getValue();
if (null != val && val.trim().length() > 0) {
refVal = val;
break;
}
}
if (refVal != null) {
gpc = "nodes.node." + refVal + ".node-host";
result = CommandGetProperty.getProperties(
instance, gpc, PROPERTIES_FETCH_TIMEOUT);
if (result.getState() == TaskState.COMPLETED) {
for (Entry<String, String> entry
: result.getValue().entrySet()) {
String val = entry.getValue();
if (null != val && val.trim().length() > 0) {
retVal = val;
break;
}
}
}
}
}
} catch (PayaraIdeException gfie) {
LOGGER.log(Level.INFO, "Could not get http host value.", gfie);
}
return LOCALHOST.equals(retVal) ? nameOfLocalhost : retVal; // NOI18N
}
private void refreshChildren() {
PayaraInstance instance = getInstance();
RefreshModulesCookie cookie = instance.getFullNode().getLookup().lookup(RefreshModulesCookie.class);
if (cookie != null) {
cookie.refresh(null, null);
}
}
}