blob: 5d929988d6b4470f765b1d687da45eda0d78b14d [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.glassfish.common;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.netbeans.modules.glassfish.tooling.GlassFishStatus;
import org.netbeans.modules.glassfish.tooling.data.GlassFishServer;
import org.netbeans.modules.glassfish.tooling.data.GlassFishServerStatus;
import org.netbeans.modules.glassfish.tooling.data.GlassFishVersion;
import org.netbeans.modules.glassfish.tooling.utils.ServerUtils;
import org.netbeans.modules.glassfish.common.status.AuthFailureStateListener;
import org.netbeans.modules.glassfish.common.status.MonitoringInitStateListener;
import org.openide.util.NbBundle;
/**
* Server state checks public module API.
* <p/>
* This API runs GlassFish server administration commands at the background
* and is accessing server properties including administrator password stored
* in <code>Keyring</code>.<br/>
* Do not use this class in NetBeans startup code to avoid <code>Keyring</code>
* access deadlocks.
* <p/>
* @author Tomas Kraus
*/
public class GlassFishState {
////////////////////////////////////////////////////////////////////////////
// Inner classes //
////////////////////////////////////////////////////////////////////////////
/**
* Check mode.
* <p/>
* Allows to select server state check mode.
*/
public static enum Mode {
////////////////////////////////////////////////////////////////////////
// Enum values //
////////////////////////////////////////////////////////////////////////
/** Default server state check mode. All special features
* are turned off. */
DEFAULT,
/** Startup mode. Sets longer administration commands timeout
* and displays GlassFish 3.1.2 WS bug warning. */
STARTUP,
/** Refresh mode. Displays enable-secure-admin warning
* for remote servers. */
REFRESH;
////////////////////////////////////////////////////////////////////////
// Methods //
////////////////////////////////////////////////////////////////////////
/**
* Convert <code>Mode</code> value to <code>String</code>.
* <p/>
* @return A <code>String</code> representation of the value
* of this object.
*/
@Override
public String toString() {
switch(this) {
case DEFAULT: return "DEFAULT";
case STARTUP: return "STARTUP";
case REFRESH: return "REFRESH";
default: throw new IllegalStateException("Unknown Mode value");
}
}
}
////////////////////////////////////////////////////////////////////////////
// Class attributes //
////////////////////////////////////////////////////////////////////////////
/** Local logger. */
private static final Logger LOGGER
= GlassFishLogger.get(GlassFishState.class);
/** Initial server status check timeout [ms]. Maximum period of time to wait
* for status monitoring to settle down. */
private static final int INIT_MONITORING_TIMEOUT = 5000;
/**
* Start monitoring GlassFish server.
* <p/>
* This method may cause delay when server status was not monitored before
* to give status monitoring time to settle down.
* <p/>
* @param instance GlassFish server instance to be monitored.
*/
public static boolean monitor(final GlassFishServer instance) {
boolean added;
// Check if server is already being monitored.
GlassFishServerStatus status = GlassFishStatus.get(instance);
if (status == null) {
MonitoringInitStateListener listener
= new MonitoringInitStateListener();
// All state change events except UNKNOWN.
added = GlassFishStatus.add(instance, listener, false,
GlassFishStatus.OFFLINE, GlassFishStatus.STARTUP,
GlassFishStatus.ONLINE, GlassFishStatus.SHUTDOWN);
if (added) {
if (instance.getVersion() != null) {
AuthFailureStateListener authListener
= new AuthFailureStateListener(
instance.getVersion().ordinal()
>= GlassFishVersion.GF_4.ordinal());
GlassFishStatus.addChangeListener(
instance, authListener, GlassFishStatus.STARTUP);
GlassFishStatus.addErrorListener(instance, authListener);
}
try {
long startTime = System.currentTimeMillis();
long waitTime = INIT_MONITORING_TIMEOUT;
synchronized (listener) {
// Guard against spurious wakeup.
while (!listener.isWakeUp() && waitTime > 0) {
listener.wait(waitTime);
waitTime = INIT_MONITORING_TIMEOUT
+ startTime - System.currentTimeMillis();
}
}
} catch (InterruptedException ie) {
LOGGER.log(Level.FINE,
"Interrupted while waiting on server monitoring");
} finally {
GlassFishStatus.removeListener(instance, listener);
}
}
} else {
added = false;
}
return added;
}
/**
* Wait for status monitoring to resolve <code>UNKNOWN</code> state.
* <p/>
* Status monitoring listener will be removed when finished.
* <p/>
* @param instance GlassFish server instance.
* @param listener Already active status monitoring listener waiting
* for leaving <code>UNKNOWN</code> state.
* @param timeout How log to wait for <code>UNKNOWN</code> state
* to be resolved in ms.
*/
private static void waitForKnownState(final GlassFishServer instance,
final MonitoringInitStateListener listener, final long timeout) {
try {
long startTime = System.currentTimeMillis();
long waitTime = timeout;
synchronized (listener) {
// Guard against spurious wakeup.
while (!listener.isWakeUp() && waitTime > 0) {
listener.wait(waitTime);
waitTime = timeout
+ startTime - System.currentTimeMillis();
}
}
} catch (InterruptedException ie) {
LOGGER.log(Level.FINE,
"Interrupted while waiting on server monitoring");
} finally {
GlassFishStatus.removeListener(instance, listener);
}
}
/**
* Retrieve GlassFish server status object from status monitoring.
* <p/>
* Can block up to <code>timeout</code> ms when server monitoring
* was suspended to wait for new status check to finish. Do not use
* with non zero <code>timeout</code> in AWT event queue thread.
* <p/>
* @param instance GlassFish server instance.
* @param timeout How log to wait for <code>UNKNOWN</code> state
* to be resolved. Value of <code>0</code> turns blocking
* off.
* @return GlassFish server status object.
* @throws IllegalStateException when status object is null even after
* monitoring of this instance was explicitely started.
*/
public static GlassFishServerStatus getStatus(
final GlassFishServer instance, final long timeout) {
MonitoringInitStateListener listener = timeout > 0
? new MonitoringInitStateListener() : null;
GlassFishServerStatus status = GlassFishStatus.get(instance, listener);
if (status == null) {
monitor(instance);
status = GlassFishStatus.get(instance);
if (status == null) {
throw new IllegalStateException(NbBundle.getMessage(
GlassFishState.class,
"GlassFishState.getStatus.statusNull"));
}
} else {
if (listener != null && listener.isActive()) {
waitForKnownState(instance, listener, timeout);
}
}
return status;
}
/**
* Retrieve GlassFish server status object from status monitoring.
* <p/>
* This call is always non blocking but it will return <code>UNKNOWN</code>
* state immediately when server state monitoring is suspended.
* <p/>
* @param instance GlassFish server instance.
* @return GlassFish server status object.
* @throws IllegalStateException when status object is null even after
* monitoring of this instance was explicitely started.
*/
public static GlassFishServerStatus getStatus(
final GlassFishServer instance) {
return getStatus(instance, 0);
}
/**
* Check if GlassFish server is running in <code>DEFAULT</code> mode.
* <p/>
* Check may cause delay when server status was not monitored before
* to give status monitoring time to settle down.
* <p/>
* @param instance GlassFish server instance.
* @return Returns <code>true</code> when GlassFish server is online
* or <code>false</code> otherwise.
*/
public static boolean isOnline(final GlassFishServer instance) {
return getStatus(instance).getStatus() == GlassFishStatus.ONLINE;
}
/**
* Check if GlassFish server is offline.
* <p/>
* Check may cause delay when server status was not monitored before
* to give status monitoring time to settle down.
* <p/>
* @param instance GlassFish server instance.
* @return Returns <code>true</code> when GlassFish server offline
* or <code>false</code> otherwise.
*/
public static boolean isOffline(final GlassFishServer instance) {
return getStatus(instance).getStatus() == GlassFishStatus.OFFLINE;
}
/**
* Check if GlassFish server can be started;
* <p/>
* Server can be started only when
* <p/>
* @param instance GlassFish server instance.
* @return Value of <code>true</code> when GlassFish server can be started
* or <code>false</code> otherwise.
*/
public static boolean canStart(final GlassFishServer instance) {
GlassFishServerStatus status = getStatus(instance);
switch(status.getStatus()) {
case UNKNOWN: case ONLINE: case SHUTDOWN: case STARTUP:
return false;
default:
// Allow start even with admin port occupied.
//return !ServerUtils.isDASRunning(instance);
return true;
}
}
}