/*
*
*
* Copyright 1990-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 only, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License version 2 for more details (a copy is
* included at /legal/license.txt).
*
* You should have received a copy of the GNU General Public License
* version 2 along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 or visit www.sun.com if you need additional
* information or have any questions.
*/
package com.sun.midp.suspend;
import com.sun.midp.security.ImplicitlyTrustedClass;
import com.sun.midp.security.SecurityToken;
import com.sun.midp.security.SecurityInitializer;
import java.util.Enumeration;
import java.util.Vector;
/**
* An abstract subsystem that may contain other subsystems.
* Contained subsytems are suspended after this subsystem suspend
* and resumed prior to the subsystem resuming.
*
*/
public abstract class AbstractSubsystem implements Subsystem {
/** Class registered in SecurityInitializer. */
private static class SecurityTrusted implements ImplicitlyTrustedClass {}
/**
* Security token for provileged access to internal API's.
* Note it must stay package private.
*/
static SecurityToken classSecurityToken =
SecurityInitializer.requestToken(new SecurityTrusted());
/** State transition synchronization lock. */
final Object lock = new Object();
/** Current subsystem state. */
int state = SUSPENDED;
/** Subsystems this one depends on. */
private final Vector subsystems = new Vector();
/**
* A set of suspend dependencies. System is considered to be suspended
* when all the subsystems are suspended and all the dependencies
* removed.
*/
private final Vector dependencies = new Vector(4, 2);
/**
* Returns the current state.
* @return current state if the subsystem
*/
public final int getState() {
return state;
}
/**
* Registers a subsystem this one depends on.
* @param s subsystem this one depends on.
*/
public void registerSubsystem(Subsystem s) {
synchronized (subsystems) {
if (!subsystems.contains(s)) {
subsystems.addElement(s);
}
}
}
/**
* Unregisters a subsystem this one depends on.
* @param s subsystem this one depends on.
*/
public void unregisterSubsystem(Subsystem s) {
synchronized (subsystems) {
subsystems.removeElement(s);
}
}
/**
* If the current state is <code>SUSPENDED</code>, changes the state to
* <code>RESUMING</code>, performs object-specific activation
* operations and then changes the state to <code>ACTIVE</code>.
*/
public final void resume() throws StateTransitionException {
synchronized (lock) {
if (state == SUSPENDED) {
state = RESUMING;
Enumeration subs = subsystems.elements();
while (subs.hasMoreElements()) {
((Subsystem)subs.nextElement()).resume();
}
resumeImpl();
state = ACTIVE;
resumed();
}
}
}
/**
* If the current state is <code>ACTIVE</code>, changes the state to
* <code>SUSPENDING</code>, and initiates suspend routine. The suspend
* routine is pstponed until all suspend dependences are removed.
* If there are no dependencies currently, the suspend routine is
* invoked immediately.
*/
public void suspend() throws StateTransitionException {
synchronized (lock) {
if (state == ACTIVE) {
state = SUSPENDING;
updateSuspendStatus();
}
}
}
/**
* Adds a dependency that prevents from system suspend.
* @param dep dependency to add
*/
public void addSuspendDependency(SuspendDependency dep) {
synchronized (lock) {
if (!dependencies.contains(dep)) {
dependencies.addElement(dep);
}
}
}
/**
* Removes dependency that does not prevent from system suspend any more.
* Then invokes suspend notification if there are no dependencies left.
* @param dep dependency to remove
*/
public void removeSuspendDependency(SuspendDependency dep) {
synchronized (lock) {
dependencies.removeElement(dep);
updateSuspendStatus();
}
}
/**
* Checks if there are dependencies that prevent from system suspend,
* if there are no ones, and the state is SUSPENDING suspend routine.
* The suspend routine performs first object-specific ations then
* invokes suspend() methods for all registered subsytems.
*/
protected void updateSuspendStatus() {
synchronized (lock) {
if (state == SUSPENDING && 0 == dependencies.size()) {
suspendImpl();
Enumeration subs = subsystems.elements();
while (subs.hasMoreElements()) {
((Subsystem)subs.nextElement()).suspend();
}
state = SUSPENDED;
suspended();
}
}
}
/**
* Performs object-specific activation operations.
* Default implementation makes nothing.
*/
protected void resumeImpl() {}
/**
* Performs object-specific suspend operations.
* Default implementation makes nothing.
*/
protected void suspendImpl() {}
/**
* Confirms subsystem has been suspended. Listeners/waiters
* can be invoked here.
*/
void suspended() {}
/**
* Confirms subsystem has been resumed. Listeners/waiters
* can be invoked here.
*/
void resumed() {}
}