org.coos.javaframe.ApplicationSpec 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.javaframe;
import org.coos.actorframe.application.DomainSpec;
import org.coos.util.serialize.AFClassLoader;
import org.coos.util.serialize.AFSerializer;
import org.coos.util.serialize.HashtableHelper;
import org.coos.util.serialize.StringHelper;
import java.io.*;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
/**
* @author geir
* @author robert
*/
public class ApplicationSpec implements AFSerializer {
public static byte TRACE_FORMAT_TEXT = 0;
public static byte TRACE_FORMAT_XML = 1;
/**
* Contains one actor spec for each actor defined in this system. The actor
* type is the key
*/
private Hashtable actorSpecs;
/**
* Is the name of the application
*/
private String appName;
/**
* Specifies if the trace is enabled
*/
private boolean traceEnabled = true;
/**
* Specifies the format of trace log format. Defaults to TRACE_FORMAT_TEXT for backward compatibility.
*/
private byte traceFormat = TRACE_FORMAT_TEXT;
/**
* A short description of the application
*/
private String description;
/**
* Specifies the scheduler, threads and which actors should be run for each
* domain in this application
*/
private DomainSpec domainSpec;
/**
* Router definitions
*/
private RouterAddress routerAddress;
/**
* If stru starts the router automactically.
*/
private boolean autoStartRouter = false;
private String routerType = "S";
/**
* The class name for the scheduler to be used in this container. This is
* container specific.
*/
private String schedulerClass;
/**
* Logfile name
*/
private String logFile;
/*
* Validation
*/
private boolean error = false;
private boolean warning = false;
private boolean validated = false;
public ApplicationSpec() {
init();
}
public ApplicationSpec(String appName) {
this.appName = appName;
init();
}
private void init() {
actorSpecs = new Hashtable();
routerAddress = new RouterAddress(appName + "/tellu", "telluRouter");
// insert default domain spec
// domainSpec = new DomainSpec("default", "ActorDomain");
if (appName == null) {
appName = "Tellu";
}
logFile = "actorlog.txt";
}
public String getRouterType() {
return routerType;
}
public void setRouterType(String routerType) {
this.routerType = routerType;
}
public boolean autoStartRouter() {
return autoStartRouter;
}
public void setAutoStartRouter(boolean autoStartRouter) {
this.autoStartRouter = autoStartRouter;
}
public RouterAddress getRouterAddress() {
return routerAddress;
}
public void setRouterAddress(String name, String type) {
this.routerAddress = new RouterAddress(name, type);
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
/**
* @return the trace format
*/
public byte getTraceFormat() {
return traceFormat;
}
/**
* @param traceFormat the traceFormat to set
*/
public void setTraceFormat(byte traceFormat) {
this.traceFormat = traceFormat;
}
public boolean isTraceEnabled() {
return traceEnabled;
}
public void setTraceEnabled(boolean traceEnabled) {
this.traceEnabled = traceEnabled;
}
public String getLogFile() {
return logFile;
}
public void setLogFile(String logFile) {
this.logFile = logFile;
}
public String getAppName() {
return appName;
}
public void setAppName(String appName) {
this.appName = appName;
}
public Hashtable getActorSpecs() {
if (actorSpecs == null) {
return new Hashtable();
} else {
return actorSpecs;
}
}
public ActorSpec getActorSpec(String actorType) {
if (actorType != null) {
return (ActorSpec) actorSpecs.get(actorType);
}
return null;
}
public ActorSpec getClonedActorSpec(String actorType) {
if (actorType != null) {
ActorSpec as = (ActorSpec) actorSpecs.get(actorType);
return (ActorSpec) as.clone();
}
return new ActorSpec();
}
public void setDomainActor(String domainId, String actorType, String className) {
DomainSpec ds = new DomainSpec(domainId, actorType);
SchedulerSpec cs = new SchedulerSpec();
cs.setId(domainId);
cs.addActorType(actorType);
ds.addSchedulerSpec(cs);
addActorSpec(actorType, className);
domainSpec = ds;
}
public DomainSpec getDomainSpec() {
return domainSpec;
}
public void setDomainSpec(DomainSpec ps) {
domainSpec = ps;
}
public void addActorSpec(ActorSpec actorSpec) {
if (actorSpecs == null) {
actorSpecs = new Hashtable();
}
if (actorSpec.getActorType() == null) {
throw new ActorFrameException("ACTOR TYPE in ActorSpec is NULL. ActorSpec: " + actorSpec);
}
actorSpecs.put(actorSpec.getActorType(), actorSpec);
}
public void addActorSpec(String actorType, String classname) {
addActorSpec(new ActorSpec(actorType, classname));
}
public void removeActorSpec(String actorType) {
if (actorSpecs.containsKey(actorType)) {
actorSpecs.remove(actorType);
System.out.println("ApplicationSpec.removeActorSpecs: AppDesc for " + actorType + "removed");
}
}
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("\nAPPLICATION SPEC: " + appName);
sb.append("\n\nTRACE: " + traceEnabled);
sb.append("\n\nDESCRITION: " + traceEnabled);
if (description != null) {
sb.append("\n " + description);
}
sb.append("\n\nDOMAIN SPEC: " + domainSpec.toString());
sb.append("ACTOR SPECS: ");
Enumeration en = actorSpecs.elements();
while (en.hasMoreElements()) {
ActorSpec as = (ActorSpec) en.nextElement();
sb.append("\n" + as.toString());
}
return sb.toString();
}
public Enumeration getPartSpecs() {
return actorSpecs.elements();
}
public Enumeration getActorTypes() {
return actorSpecs.keys();
}
public String getSchedulerClass() {
return schedulerClass;
}
public void setSchedulerClass(String schedulerClass) {
this.schedulerClass = schedulerClass;
}
public void removeActorSpecs(String actorDomain) {
// todo
}
/**
* This function must implement the serialization of the object.
*
* @return a byte array with the objects data
* @throws java.io.IOException
*/
public byte[] serialize() throws IOException {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
DataOutputStream dout = new DataOutputStream(bout);
dout.write(HashtableHelper.persist(actorSpecs));
dout.write(StringHelper.persist(appName));
dout.write(StringHelper.persist(description));
dout.write(StringHelper.persist(schedulerClass));
dout.flush();
return bout.toByteArray();
}
/**
* Use this function for resurrection of the object
*
* @param data
* The serialized data containing the object data
* @throws java.io.IOException
*/
public ByteArrayInputStream deSerialize(byte[] data, AFClassLoader cl) throws IOException {
ByteArrayInputStream bin = new ByteArrayInputStream(data);
DataInputStream din = new DataInputStream(bin);
actorSpecs = HashtableHelper.resurrect(din, cl);
appName = StringHelper.resurrect(din);
description = StringHelper.resurrect(din);
schedulerClass = StringHelper.resurrect(din);
return bin;
}
public boolean containsError() {
if (!validated) {
validateAppSpec();
}
return error;
}
public boolean containsWarning() {
if (!validated) {
validateAppSpec();
}
return warning;
}
/**
* Validate the application spec for semantic errors. All actor types is
* tested for corrected parts and connectors.
*
* @return string with error and warning messages
*/
public String validateAppSpec() {
StringBuffer sb = new StringBuffer("\n\nVALIDATION OF APPLICATION SPEC: \n");
StringBuffer errors = new StringBuffer();
StringBuffer warnings = new StringBuffer();
StringBuffer info = new StringBuffer();
warning = false;
error = false;
if (appName == null || appName.length() == 0) {
warnings.append("\tNo application name\n");
warning = true;
}
if (getRouterAddress() == null) {
warnings.append("\tNo router address\n");
warning = true;
}
if (getDomainSpec() == null) {
warnings.append("No domain spec defined. Default actor ActorDomain is used\n");
warning = true;
}
if (getActorSpecs().isEmpty()) {
warnings.append("\tNo Actors are defined.\n");
warning = true;
} else {
// validate the actor types
Enumeration en = actorSpecs.elements();
while (en.hasMoreElements()) {
ActorSpec as = (ActorSpec) en.nextElement();
// validate the part description
String actor = "\tActor: " + as.getActorType();
info.append("Actor: " + as.getActorType());
info.append(" " + as.getActorClassName());
Vector parts = as.getPartDesc();
boolean ok = true;
for (int i = 0; i < parts.size(); i++) {
PartSpec ps = (PartSpec) parts.elementAt(i);
String rt = ps.getRoleType();
ActorSpec ras = getActorSpec(rt);
String str = actor + "\tPart: " + ps.getRoleType();
// test if part name is not defined
if (ras == null) {
errors.append(str + ":\tIllegal part name\n");
ok = false;
}
// test instance range
if (ps.getHigh() < ps.getLow() || ps.getHigh() == 0) {
errors.append(str + ":\tIllegal instance range [" + ps.getLow() + "," + ps.getHigh() + "]\n");
ok = false;
}
error = error || !ok;
}
// test connector descriptions
Vector connectors = as.getConnectorDesc();
ok = true;
for (int i = 0; i < connectors.size(); i++) {
ConnectorSpec cs = (ConnectorSpec) connectors.elementAt(i);
String who = "\tfrom";
String str = actor + "\tConnector name: " + cs.getName() + who;
// Check to address
String portName = cs.getFrom().getActorPort();
String type = cs.getFrom().getActorType();
String instance = cs.getFrom().getActorID();
if (type == null || getActorSpec(type) == null) {
errors.append(str + ":\tIllegal actor type: " + type + "\n");
ok = false;
} else {
if (portName != null) {
ActorSpec spec = getActorSpec(type);
// check the port name
if (spec == null || !spec.containsPortName(portName)) {
errors.append(str + ":\tIllegal port name: " + portName + " for type: " + type + "\n");
ok = false;
}
}
// check the instance name
if (instance != null && instance.length() > 0) {
PartSpec partSpec = as.getPartSpec(type);
if (partSpec == null || !partSpec.containsInstance(instance)) {
errors.append(str + ":\tIllegal instance name: " + instance + " for type: " + type
+ "\n");
ok = false;
}
}
}
// Check from address
who = "\tTo";
portName = cs.getTo().getActorPort();
type = cs.getTo().getActorType();
instance = cs.getTo().getActorID();
if (type == null || getActorSpec(type) == null) {
errors.append(str + ":\tIllegal actor type: " + type + "\n");
ok = false;
} else {
if (portName != null) {
ActorSpec spec = getActorSpec(type);
if (spec == null || !spec.containsPortName(portName)) {
errors.append(str + ":\tIllegal port name: " + portName + " for type: " + type + "\n");
ok = false;
}
}
// check the instance name
if (instance != null && instance.length() > 0) {
PartSpec partSpec = as.getPartSpec(type);
if (partSpec == null || !partSpec.containsInstance(instance)) {
errors.append(str + ":\tIllegal instance name: " + instance + " for type: " + type
+ "\n");
ok = false;
}
}
}
error = error || !ok;
}
info.append(ok ? " OK" : " ERROR");
info.append("\n");
}
}
if (error)
sb.append("\nERRORS:\n" + errors);
if (warning)
sb.append("\nWARNINGS:\n" + warnings);
sb.append("INFO:\n" + info);
validated = true;
return sb.toString();
}
}