| /* |
| * 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; |
| } |
| |
| } |
| |
| } |