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

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

/**
 * 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.*;
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 = LoggerFactory.getLogger("org.coos.actorframe");


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

    // Keeps the reference to the actor router. May be null.
    protected ActorRouterI actorRouter;

    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; } /** * Get the actor router, may be null; * * @return */ public ActorRouterI getActorRouter() { return actorRouter; } public void setActorRouter(ActorRouterI actorRouter) { this.actorRouter = actorRouter; } /** * Return static reference to Logger object * * @return Logger object */ public Logger getLogger() { return logger; } /** * Adds an adapter to the default scheduler. This adapther may behave like a StateMachine. * @param schedulableAdapter is the adapter that implements the Scheduable interface */ public void addSchedulerAdapter(Schedulable schedulableAdapter) { schedulerData.getDefaultScheduler().addSchedulable(schedulableAdapter, schedulableAdapter.getMyActorAddress()); } /* * 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 addSchedulerAdapter(new SchedulableAdapter(sender) { public boolean 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 { if (getScheduler().isTraceOn()) logger.log(TraceConstants.tlInfo, "Received message: " + sig.messageContent()); messageHandler(sig); } return true; } }); // Start the application addRouterSession(); 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 scheduler data 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); } logger.log(TraceConstants.tlInfo, "Creation of scheduler starting"); 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()); StringBuffer sb = new StringBuffer("Scheduler " + sched.getName() + " is started. Actor types: "); if (vs != null) { for (int n = 0; n < vs.size(); n++) { String s = (String) vs.elementAt(n); sb.append(s + " , " ); sched.configure(s); } } sb.append(" Threads: " + schedulerSpec.getThreads()); schedulerData.setContainer(getContainer()); schedulerData.setApplicationSpec(getApplicationSpec()); if (logger != null) { logger.log(TraceConstants.tlInfo, sb.toString()); } sched.start(); } schedulerData.getDefaultScheduler().setTrace(getApplicationSpec().isTraceEnabled()); } catch (Exception e) { logger.log(Logger.ERROR, "Failed to create scheduler. Ignored exception " + e); } logger.log(Logger.DEBUG, "Creation of scheduler finished"); return schedulerData; } public void addRouterSession() { try { String domainName = getApplicationSpec().getDomainSpec().getDomainName(); org.coos.actorframe.application.Session domainSession = getContainer().createMessageBusAdapter(domainName); if (domainSession != null) { getSchedulerData().getDefaultScheduler().addRouter(domainSession); } } catch (ActorFrameException e) { return; } } /** * 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(), schedulerData.getApplicationSpec().getDomainSpec().getActor())); 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(schedulerData.getApplicationSpec().getDomainSpec().getActor()); } String domainName = schedulerData.getActorDomainName(); if (receiver.getActorID() == null) { receiver.setActorID(domainName); } msg.setReceiverRole(receiver); if (msg.getSenderRole() == null) { 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() { logger.log(TraceConstants.tlInfo, "Application shutdown starting."); // removes the session that was connected to the router schedulerData.setTheRouterSession(null); // Stop all scheduables connected to each scheduler // The scheduler thread itself are also stopped Enumeration en = schedulerData.getSchedulerConfig().elements(); while (en.hasMoreElements()) { Scheduler scheduler = (Scheduler) en.nextElement(); scheduler.stop(); } // clear the scheduler data schedulerData.getMySystem().clear(); schedulerData.getSchedulerConfig().clear(); schedulerData.setDefaultScheduler(null); schedulerData = null; container.exit(); logger.log(TraceConstants.tlInfo, "Application shutdown completed."); } 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) { logger.log(TraceConstants.tlError, "InterruptedException thrown in applicationEnded()"); } 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