Subversion Repositories HomeAutomation

Rev

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

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