Subversion Repositories HomeAutomation

Rev

Rev 15 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | SVN | RSS feed

Rev 15 Rev 18
1
/**
1
/**
2
 * File created by Jimmy
2
 * File created by Jimmy
3
 * at 2003-dec-25 16:15:54
3
 * at 2003-dec-25 16:15:54
4
 */
4
 */
5
package Macbeth.System;
5
package Macbeth.System;
6
 
6
 
7
import Macbeth.Utilities.*;
7
import Macbeth.Utilities.*;
8
import Macbeth.XML.XMLDataHandler;
8
import Macbeth.XML.XMLDataHandler;
9
import Macbeth.XML.XMLParser;
9
import Macbeth.XML.XMLParser;
10
import Macbeth.Transports.MbLocalTransport;
10
import Macbeth.Transports.MbLocalTransport;
11
import Macbeth.Transports.MbInternetTransport;
11
import Macbeth.Transports.MbInternetTransport;
12
 
12
 
13
import java.io.*;
13
import java.io.*;
14
import java.util.Iterator;
14
import java.util.Iterator;
15
import java.util.LinkedList;
15
import java.util.LinkedList;
16
import java.util.HashMap;
16
import java.util.HashMap;
17
import java.util.List;
17
import java.util.List;
18
 
18
 
19
import org.xml.sax.SAXException;
19
import org.xml.sax.SAXException;
20
 
20
 
21
/**
21
/**
22
 * The Macbeth kernel. This is the core component that does all the
22
 * The Macbeth kernel. This is the core component that does all the
23
 * work. You need to extend this class in order to create command-line
23
 * work. You need to extend this class in order to create command-line
24
 * kernels, GUI-kernels or whatever else.
24
 * kernels, GUI-kernels or whatever else.
25
 * @author Jimmy
25
 * @author Jimmy
26
 */
26
 */
27
public abstract class MbKernel extends MbComponent {
27
public abstract class MbKernel extends MbComponent {
28
 
28
 
29
    //list of all existing modules (module names mapped to module class names)
29
    //list of all existing modules (module names mapped to module class names)
30
    protected HashMap moduleList;
30
    protected HashMap moduleList;
31
    //list of loaded modules (module names mapped to module objects)
31
    //list of loaded modules (module names mapped to module objects)
32
    protected HashMap loadedModules;
32
    protected HashMap loadedModules;
33
    //our debug-output-stream (write meaningless debug-info here)
33
    //our debug-output-stream (write meaningless debug-info here)
34
    protected PrintStream _debug;
34
    protected PrintStream _debug;
35
    //our info-output-stream (write important info here)
35
    //our info-output-stream (write important info here)
36
    protected PrintStream _info;
36
    protected PrintStream _info;
37
    //our error-output-stream (write error messages here)
37
    //our error-output-stream (write error messages here)
38
    protected PrintStream _errors;
38
    protected PrintStream _errors;
39
    //our logfile-stream
39
    //our logfile-stream
40
    protected PrintStream _log;
40
    protected PrintStream _log;
41
    //a null-stream that ignores any data written to it
41
    //a null-stream that ignores any data written to it
42
    protected PrintStream _null;
42
    protected PrintStream _null;
43
    //list of packet transports
43
    //list of packet transports
44
    protected List packetTransports;
44
    protected List packetTransports;
45
    //default transports
45
    //default transports
46
    protected MbLocalTransport localTransport;
46
    protected MbLocalTransport localTransport;
47
    protected MbInternetTransport internetTransport;
47
    protected MbInternetTransport internetTransport;
48
    //packet dumper
48
    //packet dumper
49
    protected PacketDumper packetDumper;
49
    protected PacketDumper packetDumper;
50
    //our kernel configuration XML-file
50
    //our kernel configuration XML-file
51
    protected String configFile;
51
    protected String configFile;
52
    //our data repository. stores options and other data from the XML-file
52
    //our data repository. stores options and other data from the XML-file
53
    protected DataRepository dataRepository;
53
    protected DataRepository dataRepository;
54
    //this points to the options data entry inside the data repository
54
    //this points to the options data entry inside the data repository
55
    protected DataRepository.DataListItem options;
55
    protected DataRepository.DataListItem options;
56
    //in this map, all used script events are mapped to lists filled with MbActions
56
    //in this map, all used script events are mapped to lists filled with MbActions
57
    protected HashMap scriptEventActions;
57
    protected HashMap scriptEventActions;
58
 
58
 
59
    /**
59
    /**
60
     * Creates a new instance of MbKernel.
60
     * Creates a new instance of MbKernel.
61
     * @param configFile The XML-configuration file to use for this kernel.
61
     * @param configFile The XML-configuration file to use for this kernel.
62
     */
62
     */
63
    public MbKernel(String configFile) {
63
    public MbKernel(String configFile) {
64
        //construct MbComponent
64
        //construct MbComponent
65
        super();
65
        super();
66
 
66
 
67
        //remember configuration file
67
        //remember configuration file
68
        this.configFile = configFile;
68
        this.configFile = configFile;
69
 
69
 
70
        //create data repository
70
        //create data repository
71
        dataRepository = new DataRepository();
71
        dataRepository = new DataRepository();
72
        dataRepository.advancedBuild_BeginList("options");
72
        dataRepository.advancedBuild_BeginList("options");
73
        dataRepository.advancedBuild_BeginListItem();
73
        dataRepository.advancedBuild_BeginListItem();
74
        dataRepository.advancedBuild_EndListItem();
74
        dataRepository.advancedBuild_EndListItem();
75
        dataRepository.advancedBuild_EndList();
75
        dataRepository.advancedBuild_EndList();
76
        options = (DataRepository.DataListItem)dataRepository.getList("options").firstItem();
76
        options = (DataRepository.DataListItem)dataRepository.getList("options").firstItem();
77
 
77
 
78
        //set default values on all our options
78
        //set default values on all our options
79
        options.putField("kernelname", "Macbeth@" + System.getProperty("user.name").toString());
79
        options.putField("kernelname", "Macbeth@" + System.getProperty("user.name").toString());
80
        options.putField("moduledirectory", System.getProperty("user.dir") + "\\bin\\");
80
        //options.putField("moduledirectory", System.getProperty("user.dir") + "\\bin\\");
-
 
81
        options.putField("moduledirectory", System.getProperty("user.dir") + File.separator+"bin"+File.separator);
81
        options.putField("debugstream.logged", "false");
82
        options.putField("debugstream.logged", "false");
82
        options.putField("debugstream.timestamped", "false");
83
        options.putField("debugstream.timestamped", "false");
83
        options.putField("debugstream.visible", "false");
84
        options.putField("debugstream.visible", "false");
84
        options.putField("debugstream.prefix", "D ");
85
        options.putField("debugstream.prefix", "D ");
85
        options.putField("infostream.logged", "false");
86
        options.putField("infostream.logged", "false");
86
        options.putField("infostream.timestamped", "true");
87
        options.putField("infostream.timestamped", "true");
87
        options.putField("infostream.visible", "true");
88
        options.putField("infostream.visible", "true");
88
        options.putField("infostream.prefix", "I ");
89
        options.putField("infostream.prefix", "I ");
89
        options.putField("errorstream.logged", "false");
90
        options.putField("errorstream.logged", "false");
90
        options.putField("errorstream.timestamped", "true");
91
        options.putField("errorstream.timestamped", "true");
91
        options.putField("errorstream.visible", "true");
92
        options.putField("errorstream.visible", "true");
92
        options.putField("errorstream.prefix", "E ");
93
        options.putField("errorstream.prefix", "E ");
93
 
94
 
94
        //create output streams
95
        //create output streams
95
        _debug = System.out;
96
        _debug = System.out;
96
        _info = System.out;
97
        _info = System.out;
97
        _errors = System.err;
98
        _errors = System.err;
98
 
99
 
99
        //log stream will be created during startup
100
        //log stream will be created during startup
100
        _log = null;
101
        _log = null;
101
 
102
 
102
        //create null stream
103
        //create null stream
103
        _null = new PrintStream(new PipedOutputStream());
104
        _null = new PrintStream(new PipedOutputStream());
104
 
105
 
105
        //create module lists
106
        //create module lists
106
        moduleList = new HashMap(32);
107
        moduleList = new HashMap(32);
107
        loadedModules = new HashMap(32);
108
        loadedModules = new HashMap(32);
108
 
109
 
109
        //create packet transport list
110
        //create packet transport list
110
        packetTransports = new LinkedList();
111
        packetTransports = new LinkedList();
111
        //TODO: search dynamically for installed transports at runtime instead.
112
        //TODO: search dynamically for installed transports at runtime instead.
112
        //add local delivery transport
113
        //add local delivery transport
113
        localTransport = new MbLocalTransport(this);
114
        localTransport = new MbLocalTransport(this);
114
        installTransport(localTransport);
115
        installTransport(localTransport);
115
        //add internet delivery transport
116
        //add internet delivery transport
116
        internetTransport = new MbInternetTransport(this);
117
        internetTransport = new MbInternetTransport(this);
117
        installTransport(internetTransport);
118
        installTransport(internetTransport);
118
 
119
 
119
        //create packet dumper
120
        //create packet dumper
120
        packetDumper = new PacketDumper();
121
        packetDumper = new PacketDumper();
121
 
122
 
122
        //create the script map
123
        //create the script map
123
        scriptEventActions = new HashMap();
124
        scriptEventActions = new HashMap();
124
    }
125
    }
125
 
126
 
126
    /**
127
    /**
127
     * Installs a packet delivery transport into this kernel.
128
     * Installs a packet delivery transport into this kernel.
128
     * @param t The transport.
129
     * @param t The transport.
129
     */
130
     */
130
    protected void installTransport(MbPacketTransport t) {
131
    protected void installTransport(MbPacketTransport t) {
131
        packetTransports.add(t);
132
        packetTransports.add(t);
132
    }
133
    }
133
 
134
 
134
    /**
135
    /**
135
     * Gets the name of this kernel. Per default, this is
136
     * Gets the name of this kernel. Per default, this is
136
     * "Macbeth@username" where username is your computer
137
     * "Macbeth@username" where username is your computer
137
     * username.
138
     * username.
138
     * @return The kernel name.
139
     * @return The kernel name.
139
     */
140
     */
140
    public String name() {
141
    public String name() {
141
        return (String)options.getField("kernelname");
142
        return (String)options.getField("kernelname");
142
    }
143
    }
143
 
144
 
144
    /**
145
    /**
145
     * Gets a short description of the kernel. This should
146
     * Gets a short description of the kernel. This should
146
     * be kept short (1-2 lines) and should be formatted as
147
     * be kept short (1-2 lines) and should be formatted as
147
     * plain text.
148
     * plain text.
148
     * @return A short description of the kernel.
149
     * @return A short description of the kernel.
149
     */
150
     */
150
    public abstract String description();
151
    public abstract String description();
151
 
152
 
152
 
153
 
153
    /**
154
    /**
154
     * Call this when you want to trigger events from the kernel. Note that
155
     * Call this when you want to trigger events from the kernel. Note that
155
     * the event name you provide will automatically be prefixed by the string
156
     * the event name you provide will automatically be prefixed by the string
156
     * "Kernel.On" so that the final event string takes the form
157
     * "Kernel.On" so that the final event string takes the form
157
     * 'Kernel.OnXXX" where XXX is the event name you provide.
158
     * 'Kernel.OnXXX" where XXX is the event name you provide.
158
     *
159
     *
159
     * @param eventName The name of the event. Please read above.
160
     * @param eventName The name of the event. Please read above.
160
     */
161
     */
161
    private final void triggerEvent(String eventName) {
162
    private final void triggerEvent(String eventName) {
162
        triggerMacbethEvent("Kernel.On" + eventName);
163
        triggerMacbethEvent("Kernel.On" + eventName);
163
    }
164
    }
164
 
165
 
165
 
166
 
166
    /**
167
    /**
167
     * Triggers a Macbeth event. The kernel will perform all Macbeth
168
     * Triggers a Macbeth event. The kernel will perform all Macbeth
168
     * actions that are associated with this event.
169
     * actions that are associated with this event.
169
     *
170
     *
170
     * @param eventName The name of the Macbeth event that is being triggered.
171
     * @param eventName The name of the Macbeth event that is being triggered.
171
     */
172
     */
172
    public void triggerMacbethEvent(String eventName) {
173
    public void triggerMacbethEvent(String eventName) {
173
        //get all actions associated with this event
174
        //get all actions associated with this event
174
        List l = (List) scriptEventActions.get(eventName);
175
        List l = (List) scriptEventActions.get(eventName);
175
        if (l!=null) {
176
        if (l!=null) {
176
            Iterator it = l.iterator();
177
            Iterator it = l.iterator();
177
            while (it.hasNext()) {
178
            while (it.hasNext()) {
178
                MbAction a = (MbAction) it.next();
179
                MbAction a = (MbAction) it.next();
179
                try {
180
                try {
180
                    performAction(a);
181
                    performAction(a);
181
                } catch (MbActionNotPerformedException e) {
182
                } catch (MbActionNotPerformedException e) {
182
                    _errors.println("The scripted action '" + a.getActionString() + " " + a.getParameters() + "' could not be performed! (" + e.getMessage() + ")");
183
                    _errors.println("The scripted action '" + a.getActionString() + " " + a.getParameters() + "' could not be performed! (" + e.getMessage() + ")");
183
                }
184
                }
184
            }
185
            }
185
        }
186
        }
186
    }
187
    }
187
 
188
 
188
 
189
 
189
    /**
190
    /**
190
     * Performs an action (called by scripts or by the user).
191
     * Performs an action (called by scripts or by the user).
191
     * @param action The Macbeth action that should be performed.
192
     * @param action The Macbeth action that should be performed.
192
     * @throws MbActionNotPerformedException If, for some reason, this action could not be performed.
193
     * @throws MbActionNotPerformedException If, for some reason, this action could not be performed.
193
     */
194
     */
194
    protected void performAction(MbAction action) throws MbActionNotPerformedException {
195
    protected void performAction(MbAction action) throws MbActionNotPerformedException {
195
        //split the action string into owner and action name
196
        //split the action string into owner and action name
196
        String[] tokens = action.getActionString().split("\\.");
197
        String[] tokens = action.getActionString().split("\\.");
197
        if (tokens.length!=2) {
198
        if (tokens.length!=2) {
198
            throw new MbActionNotPerformedException("Invalid action string (format should be OWNER.ACTION)");
199
            throw new MbActionNotPerformedException("Invalid action string (format should be OWNER.ACTION)");
199
        }
200
        }
200
        //extract owner
201
        //extract owner
201
        String owner = tokens[0];
202
        String owner = tokens[0];
202
        String actionName = tokens[1];
203
        String actionName = tokens[1];
203
 
204
 
204
        //if the action was owned by us (that is by the kernel), let's perform it
205
        //if the action was owned by us (that is by the kernel), let's perform it
205
        if (owner.equalsIgnoreCase("Kernel")) {
206
        if (owner.equalsIgnoreCase("Kernel")) {
206
            if (actionName.equalsIgnoreCase("LoadModule")) {
207
            if (actionName.equalsIgnoreCase("LoadModule")) {
207
                try {
208
                try {
208
                    loadModule(action.getParameters());
209
                    loadModule(action.getParameters());
209
                } catch (MbModuleNotFoundException e) {
210
                } catch (MbModuleNotFoundException e) {
210
                    throw new MbActionNotPerformedException("Module not found!");
211
                    throw new MbActionNotPerformedException("Module not found!");
211
                } catch (MbModuleLoadException e) {
212
                } catch (MbModuleLoadException e) {
212
                    throw new MbActionNotPerformedException("Module found, but couldn't be loaded!");
213
                    throw new MbActionNotPerformedException("Module found, but couldn't be loaded!");
213
                }
214
                }
214
            }
215
            }
215
            else if (actionName.equalsIgnoreCase("UnloadModule")) {
216
            else if (actionName.equalsIgnoreCase("UnloadModule")) {
216
                if (!unloadModule(action.getParameters())) {
217
                if (!unloadModule(action.getParameters())) {
217
                    throw new MbActionNotPerformedException("Module not loaded!");
218
                    throw new MbActionNotPerformedException("Module not loaded!");
218
                }
219
                }
219
            }
220
            }
220
            //TODO: action that can clean up the packet queue with some filtering abilities
221
            //TODO: action that can clean up the packet queue with some filtering abilities
221
            //TODO: action that reloads all modules
222
            //TODO: action that reloads all modules
222
            else {
223
            else {
223
                throw new MbActionNotPerformedException("Unknown kernel action!");
224
                throw new MbActionNotPerformedException("Unknown kernel action!");
224
            }
225
            }
225
        }
226
        }
226
        //the action isn't owned by the kernel, so it must be owned by a module
227
        //the action isn't owned by the kernel, so it must be owned by a module
227
        else {
228
        else {
228
            //try to get the owner module
229
            //try to get the owner module
229
            MbModule m = (MbModule) loadedModules.get(owner);
230
            MbModule m = (MbModule) loadedModules.get(owner);
230
            //check if it existed
231
            //check if it existed
231
            if (m==null) {
232
            if (m==null) {
232
                throw new MbActionNotPerformedException("The module '" + owner + "' isn't loaded!");
233
                throw new MbActionNotPerformedException("The module '" + owner + "' isn't loaded!");
233
            }
234
            }
234
            //handle over the action to the module
235
            //handle over the action to the module
235
            m.performAction(action);
236
            m.performAction(action);
236
        }
237
        }
237
    }
238
    }
238
 
239
 
239
    /**
240
    /**
240
     * Starts up this kernel.
241
     * Starts up this kernel.
241
     */
242
     */
242
    public void startup() throws MbStartupException {
243
    public void startup() throws MbStartupException {
243
        _debug.println("Macbeth kernel is starting up");
244
        _debug.println("Macbeth kernel is starting up");
244
        //start up MbComponent
245
        //start up MbComponent
245
        super.startup();
246
        super.startup();
246
 
247
 
247
        //create XML parser and parse configuration file
248
        //create XML parser and parse configuration file
248
        _debug.println("Parsing kernel configuration file: " + configFile);
249
        _debug.println("Parsing kernel configuration file: " + configFile);
249
        XMLParser xmlParser = new XMLParser(new ConfigDataHandler());
250
        XMLParser xmlParser = new XMLParser(new ConfigDataHandler());
250
        try {
251
        try {
251
            xmlParser.parseFile(configFile);
252
            xmlParser.parseFile(configFile);
252
        } catch (FileNotFoundException e) {
253
        } catch (FileNotFoundException e) {
253
            _errors.println("Configuration file '" + configFile + "' not found. Default settings will be used!");
254
            _errors.println("Configuration file '" + configFile + "' not found. Default settings will be used!");
254
        } catch (IOException e) {
255
        } catch (IOException e) {
255
            _errors.println("I/O error while reading '" + configFile + "'. Default settings will be used!");
256
            _errors.println("I/O error while reading '" + configFile + "'. Default settings will be used!");
256
        } catch (SAXException e) {
257
        } catch (SAXException e) {
257
            _errors.println("XML Parsing error while reading '" + configFile + "'. Settings might have been lost. Please check syntax!");
258
            _errors.println("XML Parsing error while reading '" + configFile + "'. Settings might have been lost. Please check syntax!");
258
        }
259
        }
259
        _debug.println("Finished parsing kernel configuration file");
260
        _debug.println("Finished parsing kernel configuration file");
260
 
261
 
261
        //start up packet transport systems
262
        //start up packet transport systems
262
        _debug.println("Starting up packet transport systems:");
263
        _debug.println("Starting up packet transport systems:");
263
        Iterator it = packetTransports.iterator();
264
        Iterator it = packetTransports.iterator();
264
        while (it.hasNext()) {
265
        while (it.hasNext()) {
265
            MbPacketTransport pt = (MbPacketTransport)it.next();
266
            MbPacketTransport pt = (MbPacketTransport)it.next();
266
            if (pt!=null) {
267
            if (pt!=null) {
267
                _debug.println("  - " + pt.getName());
268
                _debug.println("  - " + pt.getName());
268
                pt.startup();
269
                pt.startup();
269
            }
270
            }
270
        }
271
        }
271
        _debug.println("OK, " + packetTransports.size() + " transports installed");
272
        _debug.println("OK, " + packetTransports.size() + " transports installed");
272
 
273
 
273
        //create a module list
274
        //create a module list
274
        _debug.println("Enumerating modules...");
275
        _debug.println("Enumerating modules...");
275
        LinkedList classList = new LinkedList();
276
        LinkedList classList = new LinkedList();
276
        try {
277
        try {
-
 
278
            //_debug.println("moduledirectory: " + options.getField("moduledirectory"));
277
            //try to load all classes that inherit from Macbeth.Systen.MbModule, since these are all modules
279
            //try to load all classes that inherit from Macbeth.Systen.MbModule, since these are all modules
278
            DynamicClassLoader.locateClasses(options.getField("moduledirectory"), "", new String[]{"Macbeth.System.MbModule"}, null, classList);
280
            DynamicClassLoader.locateClasses(options.getField("moduledirectory"), "", new String[]{"Macbeth.System.MbModule"}, null, classList);
279
        } catch (FileNotFoundException e) {
281
        } catch (FileNotFoundException e) {
280
            e.printStackTrace();
282
            e.printStackTrace();
281
        }
283
        }
282
        //iterate through the class list to find out the module names
284
        //iterate through the class list to find out the module names
283
        it = classList.iterator();
285
        it = classList.iterator();
284
        while (it.hasNext()) {
286
        while (it.hasNext()) {
285
            String classname = (String)it.next();
287
            String classname = (String)it.next();
286
            try {
288
            try {
287
                Class c = DynamicClassLoader.loadClass(options.getField("moduledirectory"), classname);
289
                Class c = DynamicClassLoader.loadClass(options.getField("moduledirectory"), classname);
288
                //construct a new module (so we can get its name)
290
                //construct a new module (so we can get its name)
289
                MbModule mod = (MbModule)c.newInstance();
291
                MbModule mod = (MbModule)c.newInstance();
290
                //save the module name mapped to the full classname in module list
292
                //save the module name mapped to the full classname in module list
291
                moduleList.put(mod.name(),classname);
293
                moduleList.put(mod.name(),classname);
292
            } catch (Exception e) {
294
            } catch (Exception e) {
293
                e.printStackTrace();
295
                e.printStackTrace();
294
            }
296
            }
295
        }
297
        }
296
        _debug.println("OK, " + Integer.toString(classList.size()) + " modules found");
298
        _debug.println("OK, " + Integer.toString(classList.size()) + " modules found");
297
 
299
 
298
        _debug.println("Setting up streams (visibility, timestamping, logging)...");
300
        _debug.println("Setting up streams (visibility, timestamping, logging)...");
299
 
301
 
300
        //create logstreams (that might be needed if logging is enabled)
302
        //create logstreams (that might be needed if logging is enabled)
301
        String logfile = "Macbeth log " + MyDateTime.now("yyyy-MM-dd HH_mm_ss") + ".log";
303
        String logfile = "Macbeth log " + MyDateTime.now("yyyy-MM-dd HH_mm_ss") + ".log";
302
 
304
 
303
        //if any logging is enabled
305
        //if any logging is enabled
304
        if (options.getField("debugstream.logged").equalsIgnoreCase("true") ||
306
        if (options.getField("debugstream.logged").equalsIgnoreCase("true") ||
305
            options.getField("infostream.logged").equalsIgnoreCase("true") ||
307
            options.getField("infostream.logged").equalsIgnoreCase("true") ||
306
            options.getField("errorstream.logged").equalsIgnoreCase("true")) {
308
            options.getField("errorstream.logged").equalsIgnoreCase("true")) {
307
            //create log stream
309
            //create log stream
308
            try {
310
            try {
309
                _log = new PrintStream(new FileOutputStream(logfile));
311
                _log = new PrintStream(new FileOutputStream(logfile));
310
            } catch (FileNotFoundException e) {
312
            } catch (FileNotFoundException e) {
311
                //the log stream has to be valid in order to proceed
313
                //the log stream has to be valid in order to proceed
312
                throw new MbStartupException("Error while trying to create the log file '" + logfile + "'!");
314
                throw new MbStartupException("Error while trying to create the log file '" + logfile + "'!");
313
            }
315
            }
314
        }
316
        }
315
 
317
 
316
        //if visibility is turned off for any of the streams, redirect them to null stream
318
        //if visibility is turned off for any of the streams, redirect them to null stream
317
        if (options.getField("debugstream.visible").equalsIgnoreCase("false")) {
319
        if (options.getField("debugstream.visible").equalsIgnoreCase("false")) {
318
            _debug = _null;
320
            _debug = _null;
319
        }
321
        }
320
        if (options.getField("infostream.visible").equalsIgnoreCase("false")) {
322
        if (options.getField("infostream.visible").equalsIgnoreCase("false")) {
321
            _info = _null;
323
            _info = _null;
322
        }
324
        }
323
        if (options.getField("errorstream.visible").equalsIgnoreCase("false")) {
325
        if (options.getField("errorstream.visible").equalsIgnoreCase("false")) {
324
            _errors = _null;
326
            _errors = _null;
325
        }
327
        }
326
 
328
 
327
        //add logging to the streams
329
        //add logging to the streams
328
        if (options.getField("debugstream.logged").equalsIgnoreCase("true")) {
330
        if (options.getField("debugstream.logged").equalsIgnoreCase("true")) {
329
            _debug = new MultipleStreamsAdapter(_debug, _log);
331
            _debug = new MultipleStreamsAdapter(_debug, _log);
330
        }
332
        }
331
        if (options.getField("infostream.logged").equalsIgnoreCase("true")) {
333
        if (options.getField("infostream.logged").equalsIgnoreCase("true")) {
332
            _info = new MultipleStreamsAdapter(_info, _log);
334
            _info = new MultipleStreamsAdapter(_info, _log);
333
        }
335
        }
334
        if (options.getField("errorstream.logged").equalsIgnoreCase("true")) {
336
        if (options.getField("errorstream.logged").equalsIgnoreCase("true")) {
335
            _errors = new MultipleStreamsAdapter(_errors, _log);
337
            _errors = new MultipleStreamsAdapter(_errors, _log);
336
        }
338
        }
337
 
339
 
338
        //add prefixes to streams
340
        //add prefixes to streams
339
        _debug = new TextFormatterStream(_debug);
341
        _debug = new TextFormatterStream(_debug);
340
        ((TextFormatterStream) _debug).setPreString(options.getField("debugstream.prefix"));
342
        ((TextFormatterStream) _debug).setPreString(options.getField("debugstream.prefix"));
341
        _info = new TextFormatterStream(_info);
343
        _info = new TextFormatterStream(_info);
342
        ((TextFormatterStream) _info).setPreString(options.getField("infostream.prefix"));
344
        ((TextFormatterStream) _info).setPreString(options.getField("infostream.prefix"));
343
        _errors = new TextFormatterStream(_errors);
345
        _errors = new TextFormatterStream(_errors);
344
        ((TextFormatterStream) _errors).setPreString(options.getField("errorstream.prefix"));
346
        ((TextFormatterStream) _errors).setPreString(options.getField("errorstream.prefix"));
345
 
347
 
346
        //add timestamps to streams
348
        //add timestamps to streams
347
        if (options.getField("debugstream.timestamped").equalsIgnoreCase("true")) {
349
        if (options.getField("debugstream.timestamped").equalsIgnoreCase("true")) {
348
            _debug = new TimeStampedStream(_debug);
350
            _debug = new TimeStampedStream(_debug);
349
        }
351
        }
350
        if (options.getField("infostream.timestamped").equalsIgnoreCase("true")) {
352
        if (options.getField("infostream.timestamped").equalsIgnoreCase("true")) {
351
            _info = new TimeStampedStream(_info);
353
            _info = new TimeStampedStream(_info);
352
        }
354
        }
353
        if (options.getField("errorstream.timestamped").equalsIgnoreCase("true")) {
355
        if (options.getField("errorstream.timestamped").equalsIgnoreCase("true")) {
354
            _errors = new TimeStampedStream(_errors);
356
            _errors = new TimeStampedStream(_errors);
355
        }
357
        }
356
 
358
 
357
        //trigger the Startup-event now so any scripted post-processing can take place
359
        //trigger the Startup-event now so any scripted post-processing can take place
358
        triggerEvent("Startup");
360
        triggerEvent("Startup");
359
 
361
 
360
        //everything is started up now
362
        //everything is started up now
361
        _info.println("Macbeth kernel started!");
363
        _info.println("Macbeth kernel started!");
362
    }
364
    }
363
 
365
 
364
    /**
366
    /**
365
     * Loads and starts up a specific module. Before any modules
367
     * Loads and starts up a specific module. Before any modules
366
     * can be loaded, the module list must have been created. The
368
     * can be loaded, the module list must have been created. The
367
     * kernel will do this during startup, so normally this is not
369
     * kernel will do this during startup, so normally this is not
368
     * a problem.
370
     * a problem.
369
     * @param moduleName The name of the module that should be loaded.
371
     * @param moduleName The name of the module that should be loaded.
370
     * @return true if this module was loaded and started successfully,
372
     * @return true if this module was loaded and started successfully,
371
     * false if not (because the module was already started!).
373
     * false if not (because the module was already started!).
372
     * @throws MbModuleNotFoundException if the specified module isn't found.
374
     * @throws MbModuleNotFoundException if the specified module isn't found.
373
     * @throws MbModuleLoadException if the module cannot be loaded and started.
375
     * @throws MbModuleLoadException if the module cannot be loaded and started.
374
     */
376
     */
375
    protected boolean loadModule(String moduleName) throws MbModuleNotFoundException, MbModuleLoadException {
377
    protected boolean loadModule(String moduleName) throws MbModuleNotFoundException, MbModuleLoadException {
376
        //if module is already loaded
378
        //if module is already loaded
377
        if (loadedModules.containsKey(moduleName)) {
379
        if (loadedModules.containsKey(moduleName)) {
378
            //get out of here
380
            //get out of here
379
            return false;
381
            return false;
380
        }
382
        }
381
        //get classname from our module list
383
        //get classname from our module list
382
        String classname = (String)moduleList.get(moduleName);
384
        String classname = (String)moduleList.get(moduleName);
383
        //if it was in the list
385
        //if it was in the list
384
        if (classname!=null) {
386
        if (classname!=null) {
385
            Class c;
387
            Class c;
386
            MbModule mod;
388
            MbModule mod;
387
            try {
389
            try {
388
                //try to load class
390
                //try to load class
389
                c = DynamicClassLoader.loadClass(options.getField("moduledirectory"),classname);
391
                c = DynamicClassLoader.loadClass(options.getField("moduledirectory"),classname);
390
                //try to create new instance (and thus, constuct the module)
392
                //try to create new instance (and thus, constuct the module)
391
                mod = (MbModule)c.newInstance();
393
                mod = (MbModule)c.newInstance();
392
            } catch (Exception e) {
394
            } catch (Exception e) {
393
                //module couldn't be loaded
395
                //module couldn't be loaded
394
                throw new MbModuleLoadException(e.getMessage());
396
                throw new MbModuleLoadException(e.getMessage());
395
            }
397
            }
396
            //work out dependencies for this module
398
            //work out dependencies for this module
397
            List dependencies = mod.getDependencies();
399
            List dependencies = mod.getDependencies();
398
            //if there are dependencies
400
            //if there are dependencies
399
            if (!dependencies.isEmpty()) {
401
            if (!dependencies.isEmpty()) {
400
                //for each dependency
402
                //for each dependency
401
                Iterator it = dependencies.iterator();
403
                Iterator it = dependencies.iterator();
402
                while (it.hasNext()) {
404
                while (it.hasNext()) {
403
                    String dpmod = (String)it.next();
405
                    String dpmod = (String)it.next();
404
                    if (!loadedModules.containsKey(dpmod)) {
406
                    if (!loadedModules.containsKey(dpmod)) {
405
                        _info.println("'" + mod.name() + "' depends on '" + dpmod + "'. This module will now be loaded as well!");
407
                        _info.println("'" + mod.name() + "' depends on '" + dpmod + "'. This module will now be loaded as well!");
406
                        loadModule(dpmod);
408
                        loadModule(dpmod);
407
                    }
409
                    }
408
                }
410
                }
409
            }
411
            }
410
            //try to start up module now
412
            //try to start up module now
411
            mod.setParentKernel(this);
413
            mod.setParentKernel(this);
412
            try {
414
            try {
413
                mod.startup();
415
                mod.startup();
414
                //put module in our loaded modules-list
416
                //put module in our loaded modules-list
415
                loadedModules.put(mod.name(), mod);
417
                loadedModules.put(mod.name(), mod);
416
            }
418
            }
417
            //if module failed to start up
419
            //if module failed to start up
418
            catch (MbStartupException e) {
420
            catch (MbStartupException e) {
419
                _errors.println("Module '" + mod.name() + "' failed to load! (" + e.getMessage() + ")");
421
                _errors.println("Module '" + mod.name() + "' failed to load! (" + e.getMessage() + ")");
420
                //shut down the parts of the module that were started up
422
                //shut down the parts of the module that were started up
421
                mod.shutdown();
423
                mod.shutdown();
422
                //and throw exception
424
                //and throw exception
423
                throw new MbModuleLoadException(e.getMessage());
425
                throw new MbModuleLoadException(e.getMessage());
424
            }
426
            }
425
        }
427
        }
426
        //module wasn't found
428
        //module wasn't found
427
        else {
429
        else {
428
            //so throw exception
430
            //so throw exception
429
            throw new MbModuleNotFoundException("Module not found in module list!");
431
            throw new MbModuleNotFoundException("Module not found in module list!");
430
        }
432
        }
431
        return true;
433
        return true;
432
    }
434
    }
433
 
435
 
434
    /**
436
    /**
435
     * Shuts down and unloads a specific module.
437
     * Shuts down and unloads a specific module.
436
     * @param moduleName The name of the module that should be unloaded.
438
     * @param moduleName The name of the module that should be unloaded.
437
     * @return true if the module was shut down, false if not (because
439
     * @return true if the module was shut down, false if not (because
438
     * it wasn't even started in the first place!).
440
     * it wasn't even started in the first place!).
439
     */
441
     */
440
    protected boolean unloadModule(String moduleName) {
442
    protected boolean unloadModule(String moduleName) {
441
        //get the module from the enumeration list
443
        //get the module from the enumeration list
442
        MbModule mod = (MbModule)loadedModules.get(moduleName);
444
        MbModule mod = (MbModule)loadedModules.get(moduleName);
443
        //if module was found (and thus, loaded)
445
        //if module was found (and thus, loaded)
444
        if (mod != null) {
446
        if (mod != null) {
445
            //shut it down
447
            //shut it down
446
            mod.shutdown();
448
            mod.shutdown();
447
            loadedModules.remove(moduleName);
449
            loadedModules.remove(moduleName);
448
        }
450
        }
449
        //module wasn't started
451
        //module wasn't started
450
        else {
452
        else {
451
            return false;
453
            return false;
452
        }
454
        }
453
        return true;
455
        return true;
454
    }
456
    }
455
 
457
 
456
    /**
458
    /**
457
     * Returns a given macbeth module. The module must be loaded
459
     * Returns a given macbeth module. The module must be loaded
458
     * in this local kernel, or else an exception will be thrown.
460
     * in this local kernel, or else an exception will be thrown.
459
     * @param moduleName Classname of the module.
461
     * @param moduleName Classname of the module.
460
     * @return The module. Null if it isn't found (that is, not loaded).
462
     * @return The module. Null if it isn't found (that is, not loaded).
461
     * be found within this kernel.
463
     * be found within this kernel.
462
     */
464
     */
463
    public MbModule getModule(String moduleName) {
465
    public MbModule getModule(String moduleName) {
464
        return (MbModule)loadedModules.get(moduleName);
466
        return (MbModule)loadedModules.get(moduleName);
465
    }
467
    }
466
 
468
 
467
    /**
469
    /**
468
     * Shuts down this kernel. Modules will be shut
470
     * Shuts down this kernel. Modules will be shut
469
     * down and removed from module collection.
471
     * down and removed from module collection.
470
     */
472
     */
471
    public void shutdown() {
473
    public void shutdown() {
472
        _debug.println("Macbeth kernel is about to shut down");
474
        _debug.println("Macbeth kernel is about to shut down");
473
 
475
 
474
        //trigger shutdown-event first so any scripted pre-processing can take place
476
        //trigger shutdown-event first so any scripted pre-processing can take place
475
        triggerEvent("Shutdown");
477
        triggerEvent("Shutdown");
476
 
478
 
477
        //shut down any loaded modules
479
        //shut down any loaded modules
478
        if (!loadedModules.isEmpty()) {
480
        if (!loadedModules.isEmpty()) {
479
            _debug.println("Shutting down started modules:");
481
            _debug.println("Shutting down started modules:");
480
            //iterate through all loaded modules
482
            //iterate through all loaded modules
481
            Iterator it = loadedModules.keySet().iterator();
483
            Iterator it = loadedModules.keySet().iterator();
482
            while (it.hasNext()) {
484
            while (it.hasNext()) {
483
                //shut down each loaded module
485
                //shut down each loaded module
484
                String modname = (String)it.next();
486
                String modname = (String)it.next();
485
                unloadModule(modname);
487
                unloadModule(modname);
486
                //we have removed a module from the map, so iterator needs to be re-initialized!
488
                //we have removed a module from the map, so iterator needs to be re-initialized!
487
                it = loadedModules.keySet().iterator();
489
                it = loadedModules.keySet().iterator();
488
            }
490
            }
489
        }
491
        }
490
 
492
 
491
        //shut down packet transport systems
493
        //shut down packet transport systems
492
        if (!packetTransports.isEmpty()) {
494
        if (!packetTransports.isEmpty()) {
493
            _debug.println("Shutting down packet transport systems");
495
            _debug.println("Shutting down packet transport systems");
494
            Iterator it = packetTransports.iterator();
496
            Iterator it = packetTransports.iterator();
495
            while (it.hasNext()) {
497
            while (it.hasNext()) {
496
                MbPacketTransport t = (MbPacketTransport)it.next();
498
                MbPacketTransport t = (MbPacketTransport)it.next();
497
                if (t!=null) {
499
                if (t!=null) {
498
                    t.shutdown();
500
                    t.shutdown();
499
                }
501
                }
500
            }
502
            }
501
        }
503
        }
502
 
504
 
503
        _info.println("Macbeth kernel successfully shut down");
505
        _info.println("Macbeth kernel successfully shut down");
504
 
506
 
505
        //shut down stream logging
507
        //shut down stream logging
506
        if (_log!=null) {
508
        if (_log!=null) {
507
            _log.close();
509
            _log.close();
508
        }
510
        }
509
 
511
 
510
        //shutdown MbComponent
512
        //shutdown MbComponent
511
        super.shutdown();
513
        super.shutdown();
512
    }
514
    }
513
 
515
 
514
    /**
516
    /**
515
     * Will be called when a packet needs to be delivered to
517
     * Will be called when a packet needs to be delivered to
516
     * its specified destination module.
518
     * its specified destination module.
517
     * @param p The packet that needs to be handled.
519
     * @param p The packet that needs to be handled.
518
     */
520
     */
519
    public void handlePacket(MbPacket p) {
521
    public void handlePacket(MbPacket p) {
520
        //iterate through all registered packet transports
522
        //iterate through all registered packet transports
521
        Iterator it = packetTransports.iterator();
523
        Iterator it = packetTransports.iterator();
522
        boolean deliverySuccessful = false;
524
        boolean deliverySuccessful = false;
523
        while (it.hasNext()) {
525
        while (it.hasNext()) {
524
            //try to deliver with each transport
526
            //try to deliver with each transport
525
            MbPacketTransport t = (MbPacketTransport)it.next();
527
            MbPacketTransport t = (MbPacketTransport)it.next();
526
            if (t!=null) {
528
            if (t!=null) {
527
                try {
529
                try {
528
                    deliverySuccessful = t.deliverPacket(p);
530
                    deliverySuccessful = t.deliverPacket(p);
529
                } catch (MbPacketTransport.MbPacketDeliveryException e) {
531
                } catch (MbPacketTransport.MbPacketDeliveryException e) {
530
                    //the transport attempted to deliver the packet, but failed
532
                    //the transport attempted to deliver the packet, but failed
531
                    _errors.println("Packet delivery error: " + e.getMessage());
533
                    _errors.println("Packet delivery error: " + e.getMessage());
532
                    //dump the packet
534
                    //dump the packet
533
                    packetDumper.dumpPacket(p,t.getName() + " attempted to deliver the packet, but failed with the message \"" + e.getMessage() + "\"");
535
                    packetDumper.dumpPacket(p,t.getName() + " attempted to deliver the packet, but failed with the message \"" + e.getMessage() + "\"");
534
                    //and get out of here
536
                    //and get out of here
535
                    return;
537
                    return;
536
                }
538
                }
537
                //if delivery was successful
539
                //if delivery was successful
538
                if (deliverySuccessful) {
540
                if (deliverySuccessful) {
539
                    //get out of here
541
                    //get out of here
540
                    return;
542
                    return;
541
                }
543
                }
542
            }
544
            }
543
        }
545
        }
544
        //no transport could deliver the packet, so dump it
546
        //no transport could deliver the packet, so dump it
545
        packetDumper.dumpPacket(p,"None of the transports could deliver this packet!");
547
        packetDumper.dumpPacket(p,"None of the transports could deliver this packet!");
546
    }
548
    }
547
 
549
 
548
 
550
 
549
    /**
551
    /**
550
     * A data handler for the XML-configuration file parser.
552
     * A data handler for the XML-configuration file parser.
551
     */
553
     */
552
    public class ConfigDataHandler implements XMLDataHandler {
554
    public class ConfigDataHandler implements XMLDataHandler {
553
        private String currentEvent = null;
555
        private String currentEvent = null;
554
 
556
 
555
        public void XMLstartElement(String element, HashMap attributes) {
557
        public void XMLstartElement(String element, HashMap attributes) {
556
            if (element.equals("list")) {
558
            if (element.equals("list")) {
557
                if (attributes.containsKey("name")) {
559
                if (attributes.containsKey("name")) {
558
                    dataRepository.advancedBuild_BeginList((String)attributes.get("name"));
560
                    dataRepository.advancedBuild_BeginList((String)attributes.get("name"));
559
                }
561
                }
560
                else {
562
                else {
561
                    _errors.println("Syntax error in '" + configFile + "': 'name'-attribute missing in 'list'-tag!");
563
                    _errors.println("Syntax error in '" + configFile + "': 'name'-attribute missing in 'list'-tag!");
562
                }
564
                }
563
            }
565
            }
564
            else if (element.equals("item")) {
566
            else if (element.equals("item")) {
565
                dataRepository.advancedBuild_BeginListItem();
567
                dataRepository.advancedBuild_BeginListItem();
566
            }
568
            }
567
            else if (element.equals("field")) {
569
            else if (element.equals("field")) {
568
                if (attributes.containsKey("name") && attributes.containsKey("value")) {
570
                if (attributes.containsKey("name") && attributes.containsKey("value")) {
569
                    dataRepository.advancedBuild_PutField((String)attributes.get("name"), (String)attributes.get("value"));
571
                    dataRepository.advancedBuild_PutField((String)attributes.get("name"), (String)attributes.get("value"));
570
                }
572
                }
571
                else {
573
                else {
572
                    _errors.println("Syntax error in '" + configFile + "': 'name' and/or 'value'-attributes missing in 'datafield'-tag!");
574
                    _errors.println("Syntax error in '" + configFile + "': 'name' and/or 'value'-attributes missing in 'datafield'-tag!");
573
                }
575
                }
574
            }
576
            }
575
            else if (element.equalsIgnoreCase("option")) {
577
            else if (element.equalsIgnoreCase("option")) {
576
                if (attributes.containsKey("name") && attributes.containsKey("value")) {
578
                if (attributes.containsKey("name") && attributes.containsKey("value")) {
577
                    options.putField((String)attributes.get("name"), (String)attributes.get("value"));
579
                    options.putField((String)attributes.get("name"), (String)attributes.get("value"));
578
                }
580
                }
579
                else {
581
                else {
580
                    _errors.println("Syntax error in '" + configFile + "': 'name'- and/or 'value'-attributes are missing in an 'option'-tag!");
582
                    _errors.println("Syntax error in '" + configFile + "': 'name'- and/or 'value'-attributes are missing in an 'option'-tag!");
581
                }
583
                }
582
            }
584
            }
583
            else if (element.equalsIgnoreCase("event")) {
585
            else if (element.equalsIgnoreCase("event")) {
584
                if (attributes.containsKey("name")) {
586
                if (attributes.containsKey("name")) {
585
                    currentEvent = (String) attributes.get("name");
587
                    currentEvent = (String) attributes.get("name");
586
                }
588
                }
587
                else {
589
                else {
588
                    _errors.println("Syntax error in '" + configFile + "': 'name'-attribute missing in an 'event'-tag!");
590
                    _errors.println("Syntax error in '" + configFile + "': 'name'-attribute missing in an 'event'-tag!");
589
                }
591
                }
590
            }
592
            }
591
            else if (element.equalsIgnoreCase("do")) {
593
            else if (element.equalsIgnoreCase("do")) {
592
                if (attributes.containsKey("action")) {
594
                if (attributes.containsKey("action")) {
593
                    String action = (String) attributes.get("action");
595
                    String action = (String) attributes.get("action");
594
                    String params = (String) attributes.get("params");
596
                    String params = (String) attributes.get("params");
595
                    //get the list of actions that are associated with this event so far
597
                    //get the list of actions that are associated with this event so far
596
                    List actionList = (List) scriptEventActions.get(currentEvent);
598
                    List actionList = (List) scriptEventActions.get(currentEvent);
597
                    //is this the first action associated with this event?
599
                    //is this the first action associated with this event?
598
                    if (actionList==null) {
600
                    if (actionList==null) {
599
                        //if so, a new list needs to be created
601
                        //if so, a new list needs to be created
600
                        actionList = new LinkedList();
602
                        actionList = new LinkedList();
601
                        //..and put into the events-actions-map
603
                        //..and put into the events-actions-map
602
                        scriptEventActions.put(currentEvent,actionList);
604
                        scriptEventActions.put(currentEvent,actionList);
603
                    }
605
                    }
604
                    //now, add the new action to the list
606
                    //now, add the new action to the list
605
                    actionList.add(new MbAction(action, params));
607
                    actionList.add(new MbAction(action, params));
606
                }
608
                }
607
                else {
609
                else {
608
                    _errors.println("Syntax error in '" + configFile + "': 'action'-attribute missing in a 'do'-tag!");
610
                    _errors.println("Syntax error in '" + configFile + "': 'action'-attribute missing in a 'do'-tag!");
609
                }
611
                }
610
            }
612
            }
611
        }
613
        }
612
 
614
 
613
        public void XMLendElement(String element) {
615
        public void XMLendElement(String element) {
614
            if (element.equals("list")) {
616
            if (element.equals("list")) {
615
                dataRepository.advancedBuild_EndList();
617
                dataRepository.advancedBuild_EndList();
616
            }
618
            }
617
            else if (element.equals("item")) {
619
            else if (element.equals("item")) {
618
                dataRepository.advancedBuild_EndListItem();
620
                dataRepository.advancedBuild_EndListItem();
619
            }
621
            }
620
            else if (element.equals("event")) {
622
            else if (element.equals("event")) {
621
                currentEvent = null;
623
                currentEvent = null;
622
            }
624
            }
623
        }
625
        }
624
        public void XMLelementData(String data) {}
626
        public void XMLelementData(String data) {}
625
        public void XMLdocumentStart() {}
627
        public void XMLdocumentStart() {}
626
        public void XMLdocumentEnd() {}
628
        public void XMLdocumentEnd() {}
627
    }
629
    }
628
 
630
 
629
 
631
 
630
    /**
632
    /**
631
     * A packet dumper. This is invoked to kill packets that cannot be
633
     * A packet dumper. This is invoked to kill packets that cannot be
632
     * delivered. All packet dumps will be logged to a file,
634
     * delivered. All packet dumps will be logged to a file,
633
     */
635
     */
634
    protected class PacketDumper {
636
    protected class PacketDumper {
635
        protected PrintStream log;
637
        protected PrintStream log;
636
        protected String startupTime;
638
        protected String startupTime;
637
        protected String startupTime2;
639
        protected String startupTime2;
638
        protected int packetsDumped;
640
        protected int packetsDumped;
639
 
641
 
640
        public PacketDumper() {
642
        public PacketDumper() {
641
            //remember the startup time, because when packets are dumped for the first time
643
            //remember the startup time, because when packets are dumped for the first time
642
            //we will need to create a file whose name contains our startup time.
644
            //we will need to create a file whose name contains our startup time.
643
            startupTime = MyDateTime.now();
645
            startupTime = MyDateTime.now();
644
            startupTime2 = MyDateTime.now("yyyy-MM-dd HH_mm_ss");
646
            startupTime2 = MyDateTime.now("yyyy-MM-dd HH_mm_ss");
645
            packetsDumped = 0;
647
            packetsDumped = 0;
646
        }
648
        }
647
 
649
 
648
        protected void finalize() throws Throwable {
650
        protected void finalize() throws Throwable {
649
            if (log != null) {
651
            if (log != null) {
650
                //close log stream
652
                //close log stream
651
                log.flush();
653
                log.flush();
652
                log.close();
654
                log.close();
653
            }
655
            }
654
            super.finalize();
656
            super.finalize();
655
        }
657
        }
656
 
658
 
657
        /**
659
        /**
658
         * Dumps a packet. Call this when a packet is invalid or the packet destination
660
         * Dumps a packet. Call this when a packet is invalid or the packet destination
659
         * cannot be found. A log event will be created and the packet will be killed.
661
         * cannot be found. A log event will be created and the packet will be killed.
660
         * @param p The packet that is invalid somehow, and thus needs to be dumped.
662
         * @param p The packet that is invalid somehow, and thus needs to be dumped.
661
         * @param reason The reason why the packet needs to be dumped.
663
         * @param reason The reason why the packet needs to be dumped.
662
         */
664
         */
663
        public void dumpPacket(MbPacket p, String reason) {
665
        public void dumpPacket(MbPacket p, String reason) {
664
            if (log == null) {
666
            if (log == null) {
665
                //create log output stream
667
                //create log output stream
666
                try {
668
                try {
667
                    log = new PrintStream(new FileOutputStream("dumped packets " + startupTime2 + ".log"));
669
                    log = new PrintStream(new FileOutputStream("dumped packets " + startupTime2 + ".log"));
668
                    log.println("Macbeth session started at " + startupTime + MySystem.lineBreak);
670
                    log.println("Macbeth session started at " + startupTime + MySystem.lineBreak);
669
                } catch (FileNotFoundException e) {
671
                } catch (FileNotFoundException e) {
670
                    e.printStackTrace();
672
                    e.printStackTrace();
671
                }
673
                }
672
            }
674
            }
673
            String now = MyDateTime.now();
675
            String now = MyDateTime.now();
674
            log.println("--Packet dump log event-----------------------------------------------");
676
            log.println("--Packet dump log event-----------------------------------------------");
675
            log.println("[" + now + "]");
677
            log.println("[" + now + "]");
676
            log.println("Dump reason:");
678
            log.println("Dump reason:");
677
            log.println(reason);
679
            log.println(reason);
678
            log.println("Packet was:");
680
            log.println("Packet was:");
679
            log.println(p.serializeToString());
681
            log.println(p.serializeToString());
680
            log.println("----------------------------------------------------------------------");
682
            log.println("----------------------------------------------------------------------");
681
            log.println();
683
            log.println();
682
            _info.println("A packet was dumped! (Reason: " + reason + ")");
684
            _info.println("A packet was dumped! (Reason: " + reason + ")");
683
            p = null;
685
            p = null;
684
            packetsDumped++;
686
            packetsDumped++;
685
        }
687
        }
686
    }
688
    }
687
 
689
 
688
}
690
}
689
 
691