org.appdapter.module.basic.BasicModulator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.appdapter.lib.registry Show documentation
Show all versions of org.appdapter.lib.registry Show documentation
Pluggable object registration + query service
The newest version!
/*
* Copyright 2012 by The Appdapter Project (www.appdapter.org).
*
* 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.
*/
package org.appdapter.module.basic;
import java.util.ArrayList;
import java.util.List;
import org.appdapter.api.module.Modulator;
import org.appdapter.api.module.Module;
import org.appdapter.core.log.BasicDebugger;
/**
* @author Stu B.
*/
public class BasicModulator extends BasicDebugger implements Modulator {
// static Logger theLogger = LoggerFactory.getLogger(BasicModulator.class);
private List> myModuleList = new ArrayList>();
private Ctx myDefaultCtx;
protected boolean myAutoDetachOnFinishFlag;
public BasicModulator(Ctx defCtx, boolean autoDetachOnFinish) {
myDefaultCtx = defCtx;
myAutoDetachOnFinishFlag = autoDetachOnFinish;
}
protected static boolean isModuleInActionState(Module.State modState) {
if (modState == null) {
return false;
}
if (modState == Module.State.PRE_INIT || modState == Module.State.WAIT_TO_START || modState == Module.State.WAIT_TO_RUN_OR_STOP || modState == Module.State.POST_STOP
|| modState == Module.State.FAILED_STARTUP)
return false;
if (modState == Module.State.IN_INIT || modState == Module.State.IN_START || modState == Module.State.IN_RUN || modState == Module.State.IN_STOP)
return true;
throw new RuntimeException("Module in unknown state: " + modState);
}
protected void setDefaultContext(Ctx ctx) {
myDefaultCtx = ctx;
}
@Override public synchronized void attachModule(Module m) {
Ctx prevCtx = m.getContext();
if (prevCtx != null) {
throw new RuntimeException("[" + this + "] cannot attach module [" + m
+ "] with existing context [" + prevCtx + "]");
}
Module.State modState = m.getState();
if(isModuleInActionState(modState)) {
throw new RuntimeException("Modulator[" + this + "] cannot attach module [" + m
+ "] in action state [" + modState + "]");
}
m.setContext(myDefaultCtx);
myModuleList.add(m);
}
@Override public synchronized void detachModule(Module m) {
/*
Modulator prevMod = m.getContext();
if (prevMod != this) {
throw new RuntimeException("Modulator[" + this + "] cannot detach from module [" + m +
"] with different modulator [" + prevMod);
}
*
*/
if (!myModuleList.contains(m)) {
throw new RuntimeException("[" + this + "] cannot detach from module [" + m +
"], it is not currently attached!");
}
Module.State modState = m.getState();
if(isModuleInActionState(modState)) {
throw new RuntimeException("Modulator[" + this + "] cannot detach module [" + m
+ "] in action state [" + modState + "]");
}
m.setContext(null);
myModuleList.remove(m);
}
@Override public int getAttachedModuleCount() {
return myModuleList.size();
}
/*
*
*/
@Override public synchronized void processOneBatch() {
// process lifecycle in reverse chronological order, to ensure that a particular module can advance
// no more than one state per batch.
//TODO - verify that this thread is not already inside a callback of one of our own modules
dumpModules();
processFinishedModules();
processStoppingModules();
processRunningModules();
processStartingModules();
processInitingModules();
}
protected synchronized List> getModulesMatchingStates(Module.State... matchStates) {
List> matches = new ArrayList>();
for (Module cand : myModuleList) {
Module.State candState = cand.getState();
for (Module.State ms : matchStates) {
if (candState == ms) {
matches.add(cand);
break;
}
}
}
return matches;
}
protected synchronized List> getModulesNotMatchingStates(Module.State... excludedStates) {
List> matches = new ArrayList>();
for (Module cand : myModuleList) {
Module.State candState = cand.getState();
boolean matchedExcluded = false;
for (Module.State ms : excludedStates) {
if (candState == ms) {
matchedExcluded = true;
break;
}
}
if (!matchedExcluded) {
matches.add(cand);
}
}
return matches;
}
protected List> getUnfinishedModules() {
return getModulesNotMatchingStates(Module.State.POST_STOP, Module.State.FAILED_STARTUP);
}
protected List> getFinishedModules() {
return getModulesMatchingStates(Module.State.POST_STOP, Module.State.FAILED_STARTUP);
}
protected void processFinishedModules() {
List> finishedModules = getModulesMatchingStates(Module.State.POST_STOP, Module.State.FAILED_STARTUP);
for (Module fm : finishedModules) {
try {
fm.releaseModule();
} catch (Throwable t) {
// TODO: make sure we can get module description without further exceptions.
logError("Exception while releasing module [" + fm + "]", t);
} finally {
if (myAutoDetachOnFinishFlag) {
detachModule(fm);
}
}
}
}
protected void processStoppingModules() {
List> modulesEligibleToStop = getModulesMatchingStates(Module.State.WAIT_TO_RUN_OR_STOP);
for (Module mes : modulesEligibleToStop) {
try {
if (mes.isStopRequested()) {
mes.stop();
}
} catch (Throwable t) {
// TODO: make sure we can get module description without further exceptions.
logError("Exception while stopping module [" + mes + "]", t);
// stop should not throw. If it does throw, and state was not updated to
// POST_STOP_OR_FAILED_STARTUP, then it will be allowed to continue trying
// to run, and stop.
}
}
}
protected void processRunningModules() {
List> modulesEligibleToRun = getModulesMatchingStates(Module.State.WAIT_TO_RUN_OR_STOP);
for (Module mer : modulesEligibleToRun) {
try {
mer.runOnce();
} catch (Throwable t) {
// runOnce should not throw. But when it does, there is no administrative effect - the
// module continues in its state machines.
logError("Exception while running module [" + mer + "]", t);
}
}
}
protected void processStartingModules() {
List> modulesEligibleToStart = getModulesMatchingStates(Module.State.WAIT_TO_START);
for (Module mes : modulesEligibleToStart) {
try {
mes.start();
} catch (Throwable t) {
logWarning("Exception while starting module [" + mes + "], marking module failed state", t);
logWarning("Marking module failed state");
mes.failDuringInitOrStartup();
}
}
}
protected void processInitingModules() {
List> modulesEligibleToInit = getModulesMatchingStates(Module.State.PRE_INIT, null);
for (Module mei : modulesEligibleToInit) {
try {
mei.initModule();
} catch (Throwable t) {
logWarning("Exception while initing module [" + mei + "], marking module failed state", t);
mei.failDuringInitOrStartup();
}
}
}
public void dumpModules() {
if (checkDebugImportance(IMPO_LO)) {
logInfo(IMPO_LO, "Module Dump: [" + myModuleList + "]");
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy