All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.coos.actorframe.application.Application Maven / Gradle / Ivy

There is a newer version: 1.3.1
Show newest version
/**
 * COOS - Connected Objects Operating System (www.connectedobjects.org).
 *
 * Copyright (C) 2009 Telenor ASA and Tellu AS. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see .
 *
 * You may also contact one of the following for additional information:
 * Telenor ASA, Snaroyveien 30, N-1331 Fornebu, Norway (www.telenor.no)
 * Tellu AS, Hagalokkveien 13, N-1383 Asker, Norway (www.tellu.no)
 */
package org.coos.actorframe.application;

import java.util.Enumeration;
import java.util.Vector;

import org.coos.javaframe.ActorAddress;
import org.coos.javaframe.ApplicationSpec;
import org.coos.javaframe.Logger;
import org.coos.javaframe.LoggerFactory;
import org.coos.javaframe.SchedulableAdapter;
import org.coos.javaframe.Scheduler;
import org.coos.javaframe.SchedulerData;
import org.coos.javaframe.SchedulerSpec;
import org.coos.javaframe.StateMachine;
import org.coos.javaframe.TraceConstants;
import org.coos.javaframe.messages.AFPropertyMsg;
import org.coos.javaframe.messages.ActorMsg;
import org.coos.javaframe.messages.JFConstants;

/**
 * 
 * @author Geir Melby, Tellu AS
 * @author Robert Bjarum, Tellu AS
 */
public class Application implements ApplicationConstants, JFConstants {

	// Is the name of this applicaton
	// protected String applicationName = "appName";

	// The description of this application
	protected ApplicationSpec applicationSpec;

	// Logger
	protected static Logger logger;

	// instance varaible to this class
	protected static Application instance;

	// contains the schedulerData that is run
	protected SchedulerData schedulerData;
	// Is reference to the container that runs this application
	protected Container container;

	// is the session that connects the application to the message bus
	// protected SessionManager sessionManager;
	// Contains the state of the application. The different states are
	// defined in ApplicationConstants file
	protected int state;

	public Application(ApplicationSpec appSpec) {
		setApplicationSpec(appSpec);
		instance = this;
	}

	public Application() {
		instance = this;
	}

	/**
	 * Initialize application. Called by Container.
	 * 

* To extend the initialization of the application, implement the method * extendInitApplication(). */ public final void initApplication() { state = STATE_INITIALIZING; logger = LoggerFactory.getLogger(this.getClass().getName()); /* Call extension of this method. */ extendInitApplication(); if (applicationSpec == null) { logger.log(TraceConstants.tlWarn, "Application: applicationSpec not set."); applicationSpec = readApplicationSpec(); } state = STATE_INITIALIZED; } /** * Return static reference to Logger object * * @return Logger object */ public Logger getLogger() { return logger; } /* * public void startApplication() { startApplication(new * ActorAddress("callback", "Exithandler")); } */ /** * Starts the application. The application may run one or more domains. Each * of them is started */ public void startApplication() { ActorAddress sender = getSenderAddress(); if (getApplicationSpec() == null) { throw new NullPointerException("Application,startApplication: ApplicationSpec is null"); } DomainSpec domainSpec = getApplicationSpec().getDomainSpec(); if (domainSpec == null) { domainSpec = new org.coos.actorframe.application.DomainSpec("default", "ActorDomain"); getApplicationSpec().setDomainSpec(domainSpec); } schedulerData = createDomain(domainSpec); // add schedulable adapter to receive ROLE_PLAY-messages schedulerData.getDefaultScheduler().addSchedulable(new SchedulableAdapter(sender) { public void processMessage(ActorMsg sig) { if (sig.equals(ROLE_PLAY_ENDED_MSG)) { applicationEnded(); if (getScheduler().isTraceOn()) logger.log(TraceConstants.tlInfo, "ROLE_PLAY_ENDED_MSG: Application ended."); } else if (sig.equals(ROLE_CREATE_ACK_MSG)) { if (getScheduler().isTraceOn()) logger.log(TraceConstants.tlInfo, "ROLE_PLAY_ACK_MSG: Application created."); applictionActive(); } else if (sig.equals(ROLE_CREATE_NACK_MSG)) { if (getScheduler().isTraceOn()) logger.log(TraceConstants.tlError, "ROLE_CREATE_NACK_MSG: Application start failed."); } else if (sig.equals(SUSPENDED_MSG)) { applicationSuspended(); } else if (sig.equals(RESUMED_MSG)) { applicationResumed(); } else if (sig.equals(ROLE_UPDATE_ACK_MSG)) { applicationUpdated(); } else { messageHandler(sig); } } }, sender); // Start the application if (getApplicationSpec().autoStartRouter()) { getContainer().startRouter(); } String actorId = schedulerData.getActorDomainName(); String actorType = domainSpec.getActor(); ActorAddress receiver = new ActorAddress(actorId, actorType); AFPropertyMsg msg = new AFPropertyMsg(ROLE_CREATE_MSG, true); msg.setReceiverRole(receiver); msg.setSenderRole(sender); msg.setBoolean(ROLE_CREATE_MSG_VISIBLE, true); msg.setInt(JFConstants.TRACE_LEVEL_PROP, TraceConstants.tlWarn); getSchedulerData().getDefaultScheduler().output(msg, null); } /** * Soft restarting of the application. A msg "RESTART" is send to all actors * of the scheduleler data�s MY_SYSTEM table */ public void restart() { AFPropertyMsg msg = new AFPropertyMsg(ROLE_RESTART_MSG, true); msg.setReceiverRole(new ActorAddress(schedulerData.getActorDomainName(), "ActorDomain")); schedulerData.getDefaultScheduler().output(msg, null); } public void setApplicationSpec(ApplicationSpec applicationSpec) { this.applicationSpec = applicationSpec; } /** * Creates the domains for this actor domain. It includes for all domains * the scheduler, the definition of actors to be run in each scheduler. */ protected SchedulerData createDomain(DomainSpec domainSpec) { final String domainName; if (container == null) throw new NullPointerException("Container has not been initialized!"); if (domainSpec == null) { domainSpec = new DomainSpec("default", "ActorDomain"); } domainName = domainSpec.getDomainName(); setActorDomainName(domainName); SchedulerData schedulerData = new SchedulerData(); schedulerData.setActorDomainName(domainName); Vector schedulerSpecs = domainSpec.getSchedulerSpecs(); Scheduler sched; // parse scheduler if ((schedulerSpecs == null) || schedulerSpecs.isEmpty()) { SchedulerSpec ss = new SchedulerSpec(); ss.setId("default"); domainSpec.addSchedulerSpec(ss); } try { for (int k = 0; k < schedulerSpecs.size(); k++) { SchedulerSpec schedulerSpec = (SchedulerSpec) schedulerSpecs.elementAt(k); // create scheduler sched = (Scheduler) Class.forName(schedulerSpec.getClassName()).newInstance(); sched.setThreads(schedulerSpec.getThreads()); sched.setName(schedulerSpec.getId()); Vector vs = schedulerSpec.getActorTypes(); schedulerData.setDefaultScheduler(sched); sched.setSchedulerData(schedulerData); sched.setClassLoader(getContainer()); if (vs != null) { for (int n = 0; n < vs.size(); n++) { String s = (String) vs.elementAt(n); sched.configure(s); } } schedulerData.setContainer(getContainer()); schedulerData.setApplicationSpec(getApplicationSpec()); sched.start(); } schedulerData.getDefaultScheduler().setTrace(getApplicationSpec().isTraceEnabled()); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return schedulerData; } public void addRouterSession() { String domainName = getApplicationSpec().getDomainSpec().getDomainName(); org.coos.actorframe.application.Session domainSession = getContainer().createMessageBusAdapter(domainName); if (domainSession != null) { getSchedulerData().getDefaultScheduler().addRouter(domainSession); } } /** * Returns the shceduler data for the domain * * @return SchedulerData instance */ public SchedulerData getSchedulerData() { return schedulerData; } /** * Creates an state machine based on a class name description * * @param className * is the name of the class * @return a state machine * @throws InstantiationException * @throws IllegalAccessException * @throws ClassNotFoundException */ protected StateMachine createClass(String className) throws InstantiationException, IllegalAccessException, ClassNotFoundException { return (StateMachine) Class.forName(className).newInstance(); } /** * Deletes the application by using the actor frame protocol. RoleRemove is * send to all actor domains. The domains will then recursively send * RoleRemove to all its parts. */ public void deleteApplication() { AFPropertyMsg msg = new AFPropertyMsg(ROLE_REMOVE_MSG, true); msg.setReceiverRole(new ActorAddress(schedulerData.getActorDomainName(), "ActorDomain")); schedulerData.getDefaultScheduler().output(msg, null); } /** * Resumes alle domains of the application */ public void resume() { resume(null); } /** * Resume part of the application * * @param receiver * is the receiver of resume msg */ public void resume(ActorAddress receiver) { state = STATE_RESUMING; sendMessage(new AFPropertyMsg(RESUME_MSG, true), receiver); } /** * Suspends all the domains of the application */ public void suspend() { suspend(null); } /** * Suspends part of a the application * * @param receiver * is the receiver address of the message to suspended */ public void suspend(ActorAddress receiver) { state = STATE_SUSPENDING; sendMessage(new AFPropertyMsg(SUSPEND_MSG, true), receiver); } public void updateApplication() { state = STATE_UPDATING; sendMessage(new AFPropertyMsg(ROLE_UPDATE_MSG, true), ""); } /** * Sends an actor msg to an actor * * @param msg * is the message to be send * @param receiver * is the receiver of the message */ public void sendMessage(ActorMsg msg, String receiver) { sendMessage(msg, new ActorAddress(receiver)); } /** * Sends an actor msg to an actor * * @param msg * is the message to be send * @param receiver * is the receiver of the message */ public void sendMessage(ActorMsg msg, ActorAddress receiver) { if (receiver == null) { receiver = new ActorAddress("ActorDomain"); } String domainName = schedulerData.getActorDomainName(); if (receiver.getActorID() == null) { receiver.setActorID(domainName); } msg.setReceiverRole(receiver); msg.setSenderRole(getSenderAddress()); schedulerData.getDefaultScheduler().output(msg, null); } /** * Defines the application. The specification has to be put in the * application spec. * * @return application spec * @deprecated Use setApplicationSpec() instead */ protected ApplicationSpec readApplicationSpec() { logger.log(TraceConstants.tlFatal, "Application: applicationSpec not set and deprecated readApplicationSpec not implemented."); return null; } // @deprecated should be removed public static String getActorDomain() { return AFServiceFactory.getAFServiceProperty(ACTOR_DOMAIN_NAME); } // @deprecated should be removed. Use the application spec public static String getApplicationName() { return AFServiceFactory.getAFServiceProperty(APPLICATION_NAME); } // @deprecated should be removed. public static void setActorDomainName(String actorDomainName) { AFServiceFactory.addAFService(ACTOR_DOMAIN_NAME, actorDomainName); } // @deprecated should be removed. public void setApplicationName(String applicationName) { AFServiceFactory.addAFService(APPLICATION_NAME, applicationName); } protected void extendInitApplication() { logger.log(TraceConstants.tlInfo, "Application: extendInitApplication: no values set"); } // @deprecated Implement extendInitApplication() instead. protected final void readExternalValues() { logger.log(TraceConstants.tlInfo, "Application: readExternalValues: no values read"); } /** * Destroys all domains. The scheduler is stopped. The session is decoupled * from the router */ public void destroyApp() { // todo check how to remove session manager. It was not set schedulerData.getDefaultScheduler().removeRouter(); container.stopRouter(); schedulerData.getDefaultScheduler().destroyApp(); container.exit(); } public static Application getInstance() { return instance; } public void setContainerContext(Container container) { this.container = container; } public ApplicationSpec getApplicationSpec() { return applicationSpec; } public ActorAddress getSenderAddress() { return new ActorAddress("callback", "Exithandler"); } /** * Called when the application is resumed after it has been suspended */ protected void applicationResumed() { state = STATE_ACTIVE; logger.log(TraceConstants.tlInfo, "StartApplication: Application resumed"); } /** * Called when the application has been reconfigured. The system is in the * suspended state. */ protected void applicationUpdated() { state = STATE_UPDATED; logger.log(TraceConstants.tlInfo, "StartApplication: Application updtated"); } protected void applicationError(String reason) { logger.log(TraceConstants.tlInfo, "StartApplication: Application ERROR: " + reason); } protected void applicationSuspended() { state = STATE_SUSPENDED; logger.log(TraceConstants.tlInfo, "StartApplication: Application suspended"); } public void applictionActive() { state = STATE_ACTIVE; logger.log(TraceConstants.tlInfo, "StartApplication: Application started"); } public void applicationEnded() { try { Thread.sleep(1000); } catch (InterruptedException e) { if (LoggerFactory.isTraceOn()) { logger.log(TraceConstants.tlError, "InterruptedException thrown."); } e.printStackTrace(); } if (LoggerFactory.isTraceOn()) { logger.log(TraceConstants.tlInfo, "ROLE_PLAY_ENDED_MSG: Application shutdown starting."); } getContainer().exit(); } public void messageHandler(ActorMsg sig) { } public int getState() { return state; } public void setState(int state) { this.state = state; } public Container getContainer() { return container; } /** * Methods used to do testing and management of the this actor domain */ /** * Search the system for a state machine based on actor address. The actor * id includes the full path name susch as "/test/actorB@ActorB" * * @param id * is the instance id * @return the state machine if it exists */ public StateMachine getStateMachine(String id) { Enumeration en = getSchedulerData().getMySystem().keys(); while (en.hasMoreElements()) { String s = (String) en.nextElement(); if (s.endsWith(id)) { return (StateMachine) getSchedulerData().getMySystem().get(s); } } return null; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy