EMMA Coverage Report (generated Mon Aug 23 17:21:34 CEST 2010)
[all classes][dmg.cells.nucleus]

COVERAGE SUMMARY FOR SOURCE FILE [CellAdapter.java]

nameclass, %method, %block, %line, %
CellAdapter.java100% (1/1)38%  (26/68)24%  (413/1693)25%  (95.7/379)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class CellAdapter100% (1/1)38%  (26/68)24%  (413/1693)25%  (95.7/379)
CellAdapter (String, String): void 0%   (0/1)0%   (0/6)0%   (0/2)
ac_dump_pinboard_$_1 (Args): String 0%   (0/1)0%   (0/38)0%   (0/7)
ac_exec_context_$_1_99 (Args): String 0%   (0/1)0%   (0/45)0%   (0/9)
ac_info (Args): String 0%   (0/1)0%   (0/123)0%   (0/25)
ac_say_$_1 (Args): String 0%   (0/1)0%   (0/7)0%   (0/2)
ac_set_printout_$_1 (Args): String 0%   (0/1)0%   (0/11)0%   (0/3)
ac_show_pinboard_$_0_1 (Args): String 0%   (0/1)0%   (0/30)0%   (0/7)
ac_xgetcellinfo (Args): Object 0%   (0/1)0%   (0/3)0%   (0/1)
addCellEventListener (): void 0%   (0/1)0%   (0/5)0%   (0/2)
addCellEventListener (CellEventListener): void 0%   (0/1)0%   (0/5)0%   (0/2)
cellCreated (CellEvent): void 0%   (0/1)0%   (0/1)0%   (0/1)
cellDied (CellEvent): void 0%   (0/1)0%   (0/1)0%   (0/1)
cellExported (CellEvent): void 0%   (0/1)0%   (0/1)0%   (0/1)
checkAclPermission (Authorizable, Object, String []): void 0%   (0/1)0%   (0/36)0%   (0/9)
checkAclPermission (String, Object, String): void 0%   (0/1)0%   (0/110)0%   (0/19)
cleanUp (): void 0%   (0/1)0%   (0/1)0%   (0/1)
commandArrived (String, CommandSyntaxException): Object 0%   (0/1)0%   (0/34)0%   (0/7)
createNewCell (String, String, String [], Object []): Object 0%   (0/1)0%   (0/8)0%   (0/1)
dumpPinboard (): void 0%   (0/1)0%   (0/83)0%   (0/19)
exceptionArrived (ExceptionEvent): void 0%   (0/1)0%   (0/11)0%   (0/2)
getCellInfo (): CellInfo 0%   (0/1)0%   (0/4)0%   (0/1)
getCellVersion (): CellVersion 0%   (0/1)0%   (0/20)0%   (0/5)
getDomainContextReader (String): Reader 0%   (0/1)0%   (0/5)0%   (0/1)
getInfo (): String 0%   (0/1)0%   (0/18)0%   (0/5)
getInfo (PrintWriter): void 0%   (0/1)0%   (0/36)0%   (0/4)
initLoggingContext (): void 0%   (0/1)0%   (0/4)0%   (0/1)
loadClass (String): Class 0%   (0/1)0%   (0/5)0%   (0/1)
messageArrived (CellMessage): void 0%   (0/1)0%   (0/34)0%   (0/4)
messageToForward (CellMessage): void 0%   (0/1)0%   (0/32)0%   (0/8)
prepareRemoval (KillEvent): void 0%   (0/1)0%   (0/28)0%   (0/9)
resendMessage (CellMessage): void 0%   (0/1)0%   (0/5)0%   (0/2)
routeAdded (CellEvent): void 0%   (0/1)0%   (0/1)0%   (0/1)
routeDeleted (CellEvent): void 0%   (0/1)0%   (0/1)0%   (0/1)
sendAndWait (CellMessage, boolean, boolean, long): CellMessage 0%   (0/1)0%   (0/8)0%   (0/1)
sendAndWaitToPermanent (CellMessage, long): CellMessage 0%   (0/1)0%   (0/24)0%   (0/6)
sendMessage (CellMessage, CellMessageAnswerable, long): void 0%   (0/1)0%   (0/9)0%   (0/2)
sendMessage (CellMessage, boolean, boolean): void 0%   (0/1)0%   (0/7)0%   (0/2)
sendMessage (CellMessage, boolean, boolean, CellMessageAnswerable, long): void 0%   (0/1)0%   (0/9)0%   (0/2)
setAnswerPing (boolean): void 0%   (0/1)0%   (0/4)0%   (0/1)
setAsyncCallback (boolean): void 0%   (0/1)0%   (0/5)0%   (0/2)
setPrintoutLevel (int): void 0%   (0/1)0%   (0/5)0%   (0/1)
timeUntil (long): long 0%   (0/1)0%   (0/4)0%   (0/1)
autoCommand (Object): Object 100% (1/1)9%   (11/129)9%   (2/23)
executeLocalCommand (Object): Object 100% (1/1)13%  (14/108)17%  (4/23)
messageArrived (MessageEvent): void 100% (1/1)20%  (47/235)18%  (10.9/60)
executeDomainContext (String): void 100% (1/1)68%  (34/50)63%  (8.2/13)
CellAdapter (String, String, Args, boolean): void 100% (1/1)85%  (175/207)83%  (35/42)
CellAdapter (String, String, boolean): void 100% (1/1)85%  (11/13)92%  (1.8/2)
CellAdapter (String, String, String, boolean): void 100% (1/1)86%  (12/14)92%  (1.8/2)
createPinboard (int): void 100% (1/1)92%  (11/12)96%  (1.9/2)
<static initializer> 100% (1/1)100% (4/4)100% (1/1)
CellAdapter (String): void 100% (1/1)100% (6/6)100% (2/2)
CellAdapter (String, Args, boolean): void 100% (1/1)100% (7/7)100% (2/2)
executeSetupContext (): void 100% (1/1)100% (21/21)100% (7/7)
export (): void 100% (1/1)100% (4/4)100% (1/1)
getArgs (): Args 100% (1/1)100% (3/3)100% (1/1)
getCellDomainName (): String 100% (1/1)100% (4/4)100% (1/1)
getCellName (): String 100% (1/1)100% (4/4)100% (1/1)
getDomainContext (): Map 100% (1/1)100% (4/4)100% (1/1)
getNucleus (): CellNucleus 100% (1/1)100% (3/3)100% (1/1)
getThisMessage (): CellMessage 100% (1/1)100% (3/3)100% (1/1)
kill (): void 100% (1/1)100% (4/4)100% (1/1)
sendAndWait (CellMessage, long): CellMessage 100% (1/1)100% (8/8)100% (1/1)
sendMessage (CellMessage): void 100% (1/1)100% (5/5)100% (2/2)
setCommandExceptionEnabled (boolean): void 100% (1/1)100% (4/4)100% (2/2)
start (): void 100% (1/1)100% (6/6)100% (3/3)
toString (): String 100% (1/1)100% (4/4)100% (1/1)
useInterpreter (boolean): void 100% (1/1)100% (4/4)100% (1/1)

1package dmg.cells.nucleus;
2import dmg.cells.network.*;
3import dmg.util.*;
4import dmg.util.logback.FilterShell;
5import dmg.util.logback.FilterThresholds;
6import dmg.util.logback.RootFilterThresholds;
7import java.util.*;
8import java.io.*;
9import java.lang.reflect.*;
10 
11import org.slf4j.MDC;
12import org.slf4j.Logger;
13import org.slf4j.LoggerFactory;
14 
15/**
16 *
17 *
18 *
19 * The CellAdapter builds the basic implementation of a Cell.
20 * The CellAdapter implements all required methods of the
21 * Cell interface and performs some basic actions as long
22 * as those methods are not overloaded by a subclass of
23 * CellAdapter. CellAdapter introduces a new set of methods
24 * which provide a similiar functionallity as the original
25 * Cell callbacks, but are much easier to use.
26 * Additionally CellAdapter offers a subset of the CellNucleus
27 * methods to be called directly without storing the
28 * corresponding handle to the CellNucleus.
29 * CellAdapter has a buildin command interpreter
30 * <code>see CommandInterpreter</code> which is automatically
31 * invokes for each packet containing a plain String object.
32 * The result is returned to the sender.
33 * CellAdapter forwards and answers ping requests without
34 * informing the subclass of CellAdapter as long as this
35 * capabitity is not switched of explicitly.
36 *
37 * @author Patrick Fuhrmann
38 * @version 0.2.11, 10/22/1998
39 */
40 
41public class   CellAdapter
42    extends CommandInterpreter
43    implements Cell, CellEventListener, CellEndpoint
44{
45    private final static Logger _log =
46        LoggerFactory.getLogger(CellAdapter.class);
47 
48    /**
49     * Retry period for cell communication failures.
50     */
51    private final static long RETRY_PERIOD = 30000; // 30 seconds
52 
53    private final CellNucleus _nucleus;
54    private final Gate        _readyGate = new Gate(false);
55    private final Gate        _startGate = new Gate(false);
56    private final Args        _args;
57    private boolean     _useInterpreter = true;
58    private boolean     _returnCommandException = false;
59    private boolean     _answerPing     = true;
60    private CellMessage _currentMessage = null;
61    private String      _autoSetup      = null;
62    private String      _definedSetup   = null;
63 
64    /**
65     * Creates a Cell and the corresponding CellNucleus with the
66     * specified name. An extra boolean argument 'startNow'
67     * allows to delay the arrival of messages until the
68     * CellAdapter.start() method is called.
69     *
70     * @param cellName is the name of the newly created cell. The name
71     *                 has to be unique within the context of this CellDomain.
72     * @param args an arbitrary argument string with can be obtained
73     *        by getArgs later on.
74     * @param startNow the arrival of messages is enabled.
75     * @exception IllegalArgumentException is thrown if the name is
76     *            not unique within this CellDomain.
77     */
78    public CellAdapter(String cellName,
79                       String args,
80                       boolean startNow) {
81 
82        this(cellName,  new Args(args == null ? "" : args), startNow);
83 
84    }
85    public CellAdapter(String cellName,
86                       String cellType,
87                       String args,
88                       boolean startNow) {
89 
90        this(cellName,  cellType, new Args(args == null ? "" : args), startNow);
91 
92    }
93    public CellAdapter(String  cellName,
94                       Args    args,
95                       boolean startNow) {
96        this(cellName, "Generic", args, startNow);
97    }
98    public CellAdapter(String  cellName,
99                       String  cellType,
100                       Args    args,
101                       boolean startNow) {
102 
103        _args      = args;
104        _nucleus   = new CellNucleus(this, cellName, cellType);
105        _autoSetup = cellName + "Setup";
106 
107        createPinboard(0);
108 
109        if ((_args.argc() > 0) &&
110            ((_definedSetup = _args.argv(0)).length() > 1) &&
111            (_definedSetup.startsWith("!"))) {
112 
113            _definedSetup = _definedSetup.substring(1);
114            _args.shift();
115 
116        } else {
117            _definedSetup = null;
118        }
119 
120        if (_args.getOpt("export") != null)export();
121 
122        String async = _args.getOpt("callback");
123        if (async == null)async = (String)_nucleus.getDomainContext("callback");
124        if (async != null) {
125            if (async.equals("async")) {
126                setAsyncCallback(true);
127                _log.info("Callback set to async");
128            } else if (async.equals("sync")) {
129                setAsyncCallback(false);
130                _log.info("Callback set to sync");
131            } else _log.warn("Illegal value for 'callback' option : "+async);
132        }
133        if (_args.getOpt("replyObject") != null)setCommandExceptionEnabled(true);
134 
135        /* Instantiate management component for log filtering.
136         */
137        CellNucleus parentNucleus =
138            CellNucleus.getLogTargetForCell(MDC.get(CDC.MDC_CELL));
139        FilterThresholds parentThresholds =
140            (parentNucleus.isSystemNucleus() || parentNucleus == _nucleus)
141            ? RootFilterThresholds.getInstance()
142            : parentNucleus.getLoggingThresholds();
143 
144        FilterThresholds thresholds = new FilterThresholds(parentThresholds);
145        _nucleus.setLoggingThresholds(thresholds);
146        addCommandListener(new FilterShell(thresholds));
147 
148        if (startNow)start();
149    }
150 
151    /**
152     *  starts the delivery of messages to this cell and
153     *  executes the auto and defined Setup context.
154     *  (&lt;cellName&gt;Setup and "!&lt;setupContextName&gt;)
155     *  This method has to be called if the
156     *  contructor has been used with the startNow
157     *  argument set to 'false'.
158     *
159     */
160    public void start() {
161        executeSetupContext();
162        _startGate.open();
163    }
164    /**
165     *  Executes the ContextVariable :
166     *  &lt;cellName&gt;Setup and "!&lt;setupContextName&gt;"
167     *
168     */
169    public void executeSetupContext()
170    {
171        if (_autoSetup != null) {
172            executeDomainContext(_autoSetup);
173        }
174        _autoSetup = null;
175        if (_definedSetup != null) {
176            executeDomainContext(_definedSetup);
177        }
178        _definedSetup = null;
179    }
180 
181    protected void executeDomainContext(String name)
182    {
183        if (name != null) {
184            try {
185                Reader in = _nucleus.getDomainContextReader(name);
186                try {
187                    CellShell shell = new CellShell(this);
188                    shell.execute("context:" + name, in, new Args(""));
189                } finally {
190                    in.close();
191                }
192            } catch (FileNotFoundException e) {
193                // Ignored: Context variable is not defined
194            } catch (CommandExitException e) {
195                _log.warn(e.getMessage());
196            } catch (IOException e) {
197                _log.warn(e.getMessage());
198            }
199        }
200    }
201 
202    public void setAsyncCallback(boolean async) {
203        _nucleus.setAsyncCallback(async);
204    }
205 
206    public final static String hh_exec_context = "<var> [<arg> ...]";
207    public final static String fh_exec_context =
208        "Executes the batch script in the context variable.";
209    public String ac_exec_context_$_1_99(Args args)
210        throws IOException, CommandExitException
211    {
212        StringWriter out = new StringWriter();
213        String var = args.argv(0);
214        Reader in = _nucleus.getDomainContextReader(var);
215        try {
216            args.shift();
217            CellShell shell = new CellShell(this);
218            shell.execute("context:" + var, in, out, out, args);
219        } finally {
220            in.close();
221        }
222        return out.toString();
223    }
224 
225    /**
226     * Creates a Cell and the corresponding CellNucleus with the
227     * specified name.
228     *
229     * @param cellName is the name of the newly created cell. The name
230     *                 has to be unique within the context of this CellDomain.
231     * @exception IllegalArgumentException is thrown if the name is
232     *            not unique within this CellDomain.
233     */
234    public CellAdapter(String cellName) {
235        this(cellName, "", true);
236    }
237    /**
238     * Creates a Cell and the corresponding CellNucleus with the
239     * specified name and a set of arguments.
240     *
241     * @param cellName is the name of the newly created cell. The name
242     *                 has to be unique within the context of this CellDomain.
243     * @exception IllegalArgumentException is thrown if the name is
244     *            not unique within this CellDomain.
245     */
246    public CellAdapter(String cellName, String args) {
247        this(cellName, args, true);
248    }
249    //
250    // adapter to the nucleus
251    //
252 
253    /**
254     *  Adds a CellEventListener to the current CellNucleus.
255     * @param cel has to be an object which implements CellEventListener.
256     * @see CellEventListener
257     */
258    public void addCellEventListener(CellEventListener cel) {
259        _nucleus.addCellEventListener(cel);
260    }
261    /**
262     *  Declares this Cell to be a CellEventListener.
263     *  All methods are implemented by the CellAdapter but
264     *  don't perform any actions. The subclass has to
265     *  overwrite all those methods, it is interested in.
266     *
267     * @see CellEventListener
268     */
269    public void addCellEventListener() {
270        _nucleus.addCellEventListener(this);
271    }
272    /**
273     *  returns an Args object created from the second
274     *  argument of the constructor : this(String name, String args).
275     *
276     * @return a handle to an dmg.util.Args object.
277     *
278     * @see dmg.util.Args
279     */
280    public Args getArgs() { return _args; }
281    /**
282     *  enables or disables the return type of the buildin command interpreter.
283     *
284     * @param use enables the return of CommandExceptions.
285     */
286    public void setCommandExceptionEnabled(boolean use) {
287        _returnCommandException = use;
288    }
289    /**
290     *  enables or disables the buildin command interpreter.
291     *  The default behaviour is to use the interpreter.
292     * @param use enables the interpreter if set to 'true' otherwise
293     *            the interpreter  is disabled.
294     */
295    public void useInterpreter(boolean use) { _useInterpreter = use; }
296    /**
297     *  enables or disables the ability to answer or to forward
298     *  a ping request without calling 'messageArrived' or
299     *  'messageToForward'.
300     *  The default behaviour is to answer or to forward a ping.
301     * @param ping instructs the CellAdapter to answer or forward ping requests.
302     */
303    public void setAnswerPing(boolean ping) { _answerPing = ping; }
304    /**
305     *  returns the CellNucleus assigned to this cell. This handle
306     *  might be usefull to have access to the full nucleus functionallity.
307     *
308     * @return a handle to the CellNucleus connected to this cell.
309     */
310    public CellNucleus getNucleus() { return _nucleus; }
311 
312    /**
313     * Setup the logging context of the calling thread. Threads
314     * created from the calling thread automatically inherit this
315     * information.
316     */
317    public void initLoggingContext() { CDC.setCellsContext(_nucleus); }
318 
319    /**
320     *  informs the CellCore to remove this cell.
321     *  The cell kernel will start the kill sequence as soon as
322     *  possible.
323     */
324    protected void kill() { _nucleus.kill(); }
325    /**
326     *  returns the name of this cell.
327     * @return the name of this cell.
328     */
329    public String getCellName() { return _nucleus.getCellName(); }
330    /**
331     *  returns the name of the domain this cell resides in.
332     * @return the name of this domain.
333     */
334    public String getCellDomainName() { return _nucleus.getCellDomainName(); }
335    /**
336     * marks this cell to be exportable. This call triggers an
337     * CellExported event to be delivered to all CellEventListeners.
338     * The call should only be used for cells with a
339     * wellknown name because this name is distributed to
340     * all relevent domains as soon as a
341     * RoutingManager is
342     * running.
343     *
344     * @see dmg.cells.services.RoutingManager
345     */
346    public void   export() { _nucleus.export(); }
347    /**
348     * Defines a pinboard for this CellAdapter.
349     *
350     * @param size maximum number of lines kept by the pinboard.
351     *
352     */
353    public void createPinboard(int size)
354    {
355        _nucleus.setPinboard(new Pinboard(size <= 0 ? 200 : size));
356    }
357 
358    /**
359     * sets the printout level to the specified value. The printoutlevel
360     * determines whether the calls to say and esay produce output or are
361     * ignored. The value is '1' for stderr and '2' for stdout. A value of zero
362     * suppresses all printout.
363     *
364     * @param level
365     *            the printout level.
366     *
367     */
368    public void   setPrintoutLevel(int level) { _nucleus.setPrintoutLevel(level); }
369    /**
370     *
371     *
372     * @param className Name of the cellClass which should be created
373     * @param cellName  Name of the cell instance
374     * @param args      An array of Objects which are passed to the
375     *                  constructor of the specified cellClass.
376     *
377     */
378    public Object  createNewCell(String className,
379                                 String cellName,
380                                 String [] argsClassNames,
381                                 Object [] args)
382        throws ClassNotFoundException,
383               NoSuchMethodException,
384               SecurityException,
385               InstantiationException,
386               InvocationTargetException,
387               IllegalAccessException,
388               ClassCastException                       {
389 
390        return _nucleus.createNewCell(className, cellName,
391                                      argsClassNames, args);
392 
393    }
394 
395    public Map<String,Object> getDomainContext()
396    {
397        return _nucleus.getDomainContext();
398    }
399 
400    /**
401     *
402     * Returns a reader of the specified context Object.
403     * The method allows to read throw a 'context object'
404     * as if it was a file.
405     *
406     * @param contextName Name of the context Object.
407     *
408     */
409    public Reader getDomainContextReader(String contextName)
410        throws FileNotFoundException {
411        return _nucleus.getDomainContextReader(contextName);
412    }
413 
414    /**
415     *  sends a <code>CellMessage</code> along the specified path.
416     *
417     * @param msg the message to be sent.
418     * @exception SerializationException if the payload object of this
419     *            message is not Serializable.
420     * @exception NoRouteToCellException if the destination <code>CellPath</code>
421     *            couldn't be reached.
422     *
423     */
424    public void sendMessage(CellMessage msg)
425        throws SerializationException,
426               NoRouteToCellException    {
427        _nucleus.sendMessage(msg);
428    }
429    /**
430     *  sends a <code>CellMessage</code> along the specified path.
431     *  Two additional boolean arguments allow to specify whether
432     *  the message should only be delivered locally, remotely or
433     *  both. The callback arguments (which has to be non-null
434     *  allows to specify a Class which is informed as soon as
435     *  an answer arrived or if the timeout has expired.
436     *
437     * @param msg the message to be sent.
438     * @param locally if set to 'false' the message is not delivered
439     *                locally.
440     * @param remotely if set to 'false' the message is not delivered
441     *                 remotely.
442     * @param callback specifies a class which will be informed as
443     *                 soon as the message arrives.
444     * @param timeout  is the timeout interval in msec.
445     *
446     * @exception SerializationException if the payload object of this
447     *            message is not Serializable.
448     *
449     */
450    public void sendMessage(CellMessage msg,
451                            boolean locally,
452                            boolean remotely,
453                            CellMessageAnswerable callback,
454                            long    timeout)
455        throws SerializationException {
456        _nucleus.sendMessage(msg, locally, remotely, callback, timeout);
457    }
458    public void sendMessage(CellMessage msg,
459                            CellMessageAnswerable callback,
460                            long    timeout)
461        throws SerializationException {
462        _nucleus.sendMessage(msg, true, true, callback, timeout);
463    }
464    /**
465     *  sends a <code>CellMessage</code> along the specified path.
466     *  Two additional boolean arguments allow to specify whether
467     *  the message should only be delivered locally, remotely or
468     *  both.
469     *
470     * @param msg the message to be sent.
471     * @param locally if set to 'false' the message is not delivered
472     *                locally.
473     * @param remotely if set to 'false' the message is not delivered
474     *                 remotely.
475     * @exception SerializationException if the payload object of this
476     *            message is not Serializable.
477     * @exception NoRouteToCellException if the destination <code>CellPath</code>
478     *            couldn't be reached.
479     *
480     */
481    public void sendMessage(CellMessage msg, boolean locally,
482                            boolean remotely)
483        throws SerializationException,
484               NoRouteToCellException    {
485        _nucleus.sendMessage(msg, locally, remotely);
486    }
487    /**
488     *  sends a <code>CellMessage</code> along the specified path,
489     *  and waits <code>millisecs</code> for an answer to arrive.
490     *  The answer will bypass the ordinary queuing mechanism and
491     *  will be delivered before any other asynchronous message.
492     *  The answer need to have the getLastUOID set to the
493     *  UOID of the message send with sendAndWait. If the answer
494     *  doesn't arrive withing the specified time intervall,
495     *  the method returns 'null' and the answer will be handled
496     *  as if it was an ordinary asynchronous message.
497     *
498     * @param msg the message to be sent.
499     * @param local if 'false' the destination is not looked up locally.
500     * @param remote if 'false' the destination is not looked up remotely.
501     * @param millisecs milliseconds to wait for an answer.
502     * @return the answer CellMessage or 'null' if intervall timed out.
503     * @exception SerializationException if the payload object of this
504     *            message is not Serializable.
505     * @exception NoRouteToCellException if the destination <code>CellPath</code>
506     *            couldn't be reached.
507     *
508     */
509    public CellMessage sendAndWait(CellMessage msg,
510                                   boolean local,
511                                   boolean remote,
512                                   long millisecs)
513        throws SerializationException,
514               NoRouteToCellException,
515               InterruptedException        {
516        return _nucleus.sendAndWait(msg, local, remote, millisecs);
517    }
518    /**
519     *
520     * convenience method : identical to <br>
521     *  sendAndWait(msg, millisecs, true, true);
522     *
523     * @param msg the message to be sent.
524     * @param millisecs milliseconds to wait.
525     * @return the answer CellMessage or 'null' if intervall timed out.
526     * @exception SerializationException if the payload object of this
527     *            message is not Serializable.
528     * @exception NoRouteToCellException if the destination <code>CellPath</code>
529     *            couldn't be reached.
530     *
531     * @see dmg.cells.nucleus.CellNucleus#sendAndWait(CellMessage,long,boolean,boolean)
532     */
533    public CellMessage sendAndWait(CellMessage msg,
534                                   long millisecs)
535        throws SerializationException,
536               NoRouteToCellException,
537               InterruptedException        {
538        return _nucleus.sendAndWait(msg, true, true, millisecs);
539    }
540 
541    private long timeUntil(long time)
542    {
543        return time - System.currentTimeMillis();
544    }
545 
546    /**
547     * @see CellEndpoint.sendAndWaitToPermanent
548     */
549    public CellMessage sendAndWaitToPermanent(CellMessage envelope,
550                                              long timeout)
551        throws SerializationException,
552               InterruptedException
553    {
554        long deadline = System.currentTimeMillis() + timeout;
555        while (true) {
556            try {
557                return sendAndWait(envelope, timeUntil(deadline));
558            } catch (NoRouteToCellException e) {
559                _log.warn(e.toString(), e);
560                Thread.sleep(Math.min(timeUntil(deadline), RETRY_PERIOD));
561            }
562        }
563    }
564 
565    /**
566     *  sends a <code>CellMessage</code> along the specified path.
567     *  <strong>resendMessage does not resolve the local cell
568     *  Namespace, only the routes are inspected.</strong>
569     *
570     *
571     * @param msg the message to be sent.
572     * @exception SerializationException if the payload object of this
573     *            message is not Serializable.
574     * @exception NoRouteToCellException if the destination <code>CellPath</code>
575     *            couldn't be reached.
576     *
577     */
578    public void resendMessage(CellMessage msg)
579        throws SerializationException,
580               NoRouteToCellException    {
581        _nucleus.resendMessage(msg);
582    }
583    /**
584     *  Returns the message object which caused a
585     *  Command Interpreter client method to trigger.
586     *  The result object is only 'non-zero' inside
587     *  a ac_xxx method.
588     */
589    public CellMessage getThisMessage() {
590        return _currentMessage;
591    }
592    //
593    // methods which may be overwriten
594    //
595 
596    /**
597     * should be overwrite to provide a more specific
598     * one line information about this cell.
599     *
600     * @return a one line information String.
601     */
602    public String toString() {  return _nucleus.getCellName();  }
603    /**
604     * should be overwrite to provide more specific
605     * information about this cell.
606     *
607     * @param printWrite the printWrite which has to be used to
608     *                   write the information to.
609     *
610     */
611    public void getInfo(PrintWriter printWriter) {
612        printWriter.println(" CellName  : "+_nucleus.getCellName());
613        printWriter.println(" CellClass : "+this.getClass().getName());
614        printWriter.println(" Arguments : "+_args);
615    }
616    public CellVersion getCellVersion()
617    {
618        String pv = null;
619        Package p = Package.getPackage("dmg.cells.nucleus");
620        if (p != null) {
621            pv = p.getSpecificationVersion();
622        }
623        return new CellVersion((pv == null) ? "cells" : pv,
624                               "CA-$Revision: 1.28 $");
625    }
626    public CellInfo getCellInfo() { return _nucleus.getCellInfo(); }
627    /**
628     * has to be overwritten to receive arriving messages.
629     * The LastMessageEvent is filtered out and starts the
630     * kill sequence which calls 'cleanUp' at the end of the
631     * sequence. If the CommandInterpreter facility is enabled,
632     * all string messages are send to the command interpreter
633     * and answered without intervention of the callback.
634     * If the command could not be found by the CommandInterpreter,
635     * <link>dmg.cells.nucleus.CellAdapter#commandArrived(CellMessage)</link>
636     * is called if it is overwritten
637     * by one of the CellAdapters subclasses.
638     * This callback is only used to inform about messages of which
639     * the current cell is the final destination.
640     * Other messages are delivered throu <code>messageToForward</code>.
641     *
642     * @param msg the reference to message arrived.
643     * @see dmg.cells.nucleus.CellAdapter#commandArrived(CellMessage)
644     *
645     */
646    public void messageArrived(CellMessage msg) {
647        _log.info(" CellMessage From   : "+msg.getSourceAddress());
648        _log.info(" CellMessage To     : "+msg.getDestinationAddress());
649        _log.info(" CellMessage Object : "+msg.getMessageObject());
650 
651    }
652    /**
653     * has to be overwritten to receive arriving messages which
654     * are not directly addressed to this cell. The default behaviour
655     * is to select the next destination and to resend the message.
656     *
657     * @param msg the reference to message arrived.
658     *
659     */
660    public void messageToForward(CellMessage msg) {
661        msg.nextDestination();
662        try {
663            _nucleus.sendMessage(msg);
664        } catch (NoRouteToCellException nrtc) {
665            _log.warn("CellAdapter : NoRouteToCell in messageToForward : "+nrtc);
666        } catch (Exception eee) {
667            _log.warn("CellAdapter : Exception in messageToForward : "+eee);
668        }
669    }
670    public Class loadClass(String className) throws ClassNotFoundException {
671        return _nucleus.loadClass(className);
672    }
673 
674    /**
675     *
676     *  If overwritten this method delivers commands which
677     *  produced a syntax error which intereted by the
678     *  CommandInterpreter. The original message string
679     *  is provides together with a help text offered
680     *  by the interpreter.
681     *  If not overwritten this helptext is send back to the
682     *  caller.
683     *
684     * @param str is the orginal command string.
685     * @param cse is the syntax error exception thrown by the
686     *            command interpreter. cse.getHelpText offers
687     *            the possible help text.
688     * @return the object which is send back to the caller.
689     *             If <code>null</code> nothing is send back.
690     */
691    public Object commandArrived(String str, CommandSyntaxException cse) {
692        StringBuffer sb = new StringBuffer();
693        sb.append("Syntax Error : "+cse.getMessage()+"\n");
694        String help  = cse.getHelpText();
695        if (help != null) {
696            sb.append("Help : \n");
697            sb.append(help);
698        }
699        return sb.toString();
700    }
701    /**
702     * has to be overwritten to perform any actions before this
703     * cell is destroyed. 'cleanUp' is called after the last
704     * message has arrived. The default behaviour is to do nothing.
705     *
706     */
707    public void cleanUp() {  }
708    //
709    // methods from the cellEventListener Interface
710    //
711    /**
712     *   belongs to the CellEventListener Interface
713     */
714    public void cellCreated(CellEvent ce) {}
715    /**
716     *   belongs to the CellEventListener Interface
717     */
718    public void cellDied(CellEvent ce) {}
719    /**
720     *   belongs to the CellEventListener Interface
721     */
722    public void cellExported(CellEvent ce) {}
723    /**
724     *   belongs to the CellEventListener Interface
725     */
726    public void routeAdded(CellEvent ce) {}
727    /**
728     *   belongs to the CellEventListener Interface
729     */
730    public void routeDeleted(CellEvent ce) {}
731    //
732    // methods which are automatically scanned by
733    // the CommandInterpreterFacility
734    //
735   public String fh_set_printout =
736       "Syntax: set printout <level>\n\n"+
737       "Obsolete: Replaced by the log4j command set, see help in the\n" +
738       "          System cell. The printout level now only controls the\n" +
739       "          log level at which messages generated through the old\n" +
740       "          logging system are logged to log4j.\n\n" +
741       "  <level> Bitmask of the following fields:\n" +
742       "            1 -> log cell messages at WARN when set\n"+
743       "            2 -> log cell errors at ERROR when set\n"+
744       "            4 -> log nucleus messages at WARN when set\n"+
745       "            8 -> log nucleus error at ERROR when set\n"+
746       "          If a field is not set, then the corresponding messages\n"+
747       "          are logged at INFO level.\n";
748    public String ac_set_printout_$_1(Args args) {
749        int printout  = Integer.parseInt(args.argv(0));
750        _nucleus.setPrintoutLevel(printout);
751        return "Obsolete, see help for details";
752    }
753 
754    public String ac_say_$_1(Args args) {
755        _log.info(args.argv(0));
756        return "";
757    }
758    public Object ac_xgetcellinfo(Args args) {
759        return getCellInfo();
760    }
761    public String hh_info = "[-l|-a]";
762    public String ac_info(Args args) throws Exception {
763        boolean full = args.getOpt("a") != null;
764        boolean lng  = full || (args.getOpt("l") != null);
765        if (lng) {
766            StringBuffer sb = new StringBuffer();
767            sb.append(getInfo()).append("\n");
768            Map<UOID,CellLock > map = _nucleus.getWaitQueue();
769            if (! map.isEmpty())sb.append("\nWe are waiting for the following messages\n");
770            for (Map.Entry<UOID,CellLock > entry : map.entrySet()) {
771                Object    key   = entry.getKey();
772                CellLock  lock  = entry.getValue();
773                sb.append(key.toString()).append(" r=");
774                long res = lock.getTimeout() - System.currentTimeMillis();
775                sb.append(res/1000).append(" sec;");
776                CellMessage msg = lock.getMessage();
777                if (msg == null) {
778                    sb.append("msg=none");
779                } else {
780                    Object obj = msg.getMessageObject();
781                    if (obj != null) {
782                        sb.append("msg=").append(obj.getClass().getName());
783                        if (full)
784                            sb.append("/").append(obj.toString());
785                    }
786                }
787                sb.append("\n");
788            }
789            return sb.toString();
790        } else {
791            return getInfo();
792        }
793    }
794    public String hh_show_pinboard =
795        "[<lines>] # dumps the last <lines> to the terminal";
796    public String ac_show_pinboard_$_0_1(Args args)
797    {
798        Pinboard pinboard = _nucleus.getPinboard();
799        if (pinboard == null) return "No Pinboard defined";
800        StringBuffer sb = new StringBuffer();
801        if (args.argc() > 0) {
802            pinboard.dump(sb, Integer.parseInt(args.argv(0)));
803        } else {
804            pinboard.dump(sb, 20);
805        }
806 
807        return sb.toString();
808    }
809 
810    public String hh_dump_pinboard =
811        "<filename> # dumps the full pinboard to <filename>";
812    public String ac_dump_pinboard_$_1(Args args)
813    {
814        Pinboard pinboard = _nucleus.getPinboard();
815        if (pinboard == null) return "No Pinboard defined";
816 
817        try {
818            pinboard.dump(new File(args.argv(0)));
819        } catch (Exception e) {
820            return "Dump Failed : "+e;
821        }
822        return "Pinboard dumped to "+args.argv(0);
823    }
824 
825    /**
826     *   belongs to the Cell Interface.
827     *   If this method is overwritten, the 'cleanUp'
828     *   method won't becalled.
829     */
830    public void prepareRemoval(KillEvent ce) {
831        _log.info("CellAdapter : prepareRemoval : waiting for gate to open");
832        _readyGate.check();
833        try {
834            cleanUp();
835        } catch (Throwable t) {
836            _log.warn("CellAdapter : prepareRemoval : got "+t, t);
837        }
838        dumpPinboard();
839        _log.info("CellAdapter : prepareRemoval : done");
840    }
841    //
842    // package private (we need it in CellShell)
843    //
844    void dumpPinboard()
845    {
846        Pinboard pinboard = _nucleus.getPinboard();
847        try {
848            Map<String,Object> context = getDomainContext();
849            String dumpDir = (String)context.get("dumpDirectory");
850            if (dumpDir == null) {
851                _log.info("Pinboard not dumped (dumpDirectory not sp.)");
852                return;
853            }
854            File dir = new File(dumpDir);
855            if (! dir.isDirectory()) {
856                _log.info(
857                          "Pinboard not dumped (dumpDirectory[="+dumpDir+"] not found)");
858                return;
859            }
860            if (pinboard == null) {
861                _log.info("Pinboard not dumped (no pinboard defined)");
862                return;
863            }
864 
865            File dump = new File(dir,
866                                 getCellDomainName()+"-"+
867                                 getCellName()+"-"+
868                                 Long.toHexString(System.currentTimeMillis()));
869            pinboard.dump(dump);
870        } catch (Throwable t) {
871            _log.warn("Dumping pinboard failed : "+t);
872        }
873    }
874    /**
875     *   belongs to the Cell Interface.
876     *   Is never called.
877     */
878    public void   exceptionArrived(ExceptionEvent ce) {
879        _log.info(" exceptionArrived "+ce);
880    }
881    /**
882     *   belongs to the Cell Interface.
883     *   If this method is overwritten, the getInfo(PrintWriter pw)
884     *   is never called.
885     */
886    public String getInfo() {
887        StringWriter stringWriter = new StringWriter();
888        PrintWriter   printWriter = new PrintWriter(stringWriter);
889 
890        getInfo(printWriter);
891        printWriter.flush();
892        return stringWriter.getBuffer().toString();
893    }
894    /**
895     *   belongs to the Cell Interface.
896     *   If this method is overwritten, the messageArrived(CellMessage cm)
897     *   and the messageToForward(CellMessage) methods
898     *   are never called.
899     */
900    public void   messageArrived(MessageEvent me) {
901        _startGate.check();
902        if (me instanceof LastMessageEvent) {
903            _log.info("messageArrived : LastMessageEvent (opening gate)");
904            _readyGate.open();
905        } else {
906            CellMessage msg = me.getMessage();
907            Object      obj = msg.getMessageObject();
908            //        _log.info("messageArrived Object : [final="+
909            //               msg.isFinalDestination()+";i="+_useInterpreter+"] "+obj.getClass());
910            if (msg.isFinalDestination()) {
911                if (_useInterpreter && (! msg.isReply()) &&
912                    ((obj instanceof String) ||
913                     (obj instanceof AuthorizedString) ||
914                     (obj instanceof CommandRequestable))) {
915 
916                    Object o;
917                    UOID uoid = msg.getUOID();
918                    EventLogger.deliverBegin(msg);
919                    try {
920                        _currentMessage = msg;
921                        o =  executeLocalCommand(obj);
922                        if (o == null)
923                            return;
924                    } catch (CommandException ce) {
925                        o = ce;
926                    } catch (Throwable te) {
927                        o = te;
928                    } finally {
929                        EventLogger.deliverEnd(msg.getSession(), uoid);
930                        _currentMessage = null;
931                    }
932 
933                    try {
934                        msg.revertDirection();
935                        if (o instanceof Reply) {
936                            Reply reply = (Reply)o;
937                            reply.deliver(this, msg);
938                        } else {
939                            msg.setMessageObject(o);
940                            _nucleus.sendMessage(msg);
941                        }
942                    } catch (Exception e) {
943                        _log.warn("PANIC : Problem returning answer : " + e);
944                    }
945                } else if ((obj instanceof PingMessage) && _answerPing) {
946                    PingMessage ping = (PingMessage)obj;
947                    if (ping.isWayBack()) {
948                        messageArrived(msg);
949                        return;
950                    }
951                    ping.setWayBack();
952                    msg.revertDirection();
953                    try {
954                        _nucleus.sendMessage(msg);
955                    } catch (Exception ee) {
956                        _log.warn("Couldn't revert PingMessage : "+ee);
957                    }
958                } else {
959                    UOID uoid = msg.getUOID();
960                    EventLogger.deliverBegin(msg);
961                    try {
962                        messageArrived(msg);
963                    } finally {
964                        EventLogger.deliverEnd(msg.getSession(), uoid);
965                    }
966                }
967            } else {
968                //
969                /*
970                  if (((obj instanceof PingMessage) && _answerPing) ||
971                  (_useInterpreter &&
972                  ((obj instanceof String) ||
973                  (obj instanceof CommandRequestable)))) {
974                  msg.nextDestination();
975                  try {
976                  _nucleus.sendMessage(msg);
977                  } catch (Exception ee) {
978                  _log.warn("Couldn't forward PingMessage : "+ee);
979                  }
980                  } else {
981                  messageToForward(msg);
982                  }
983                */
984                if (obj instanceof PingMessage) {
985                    msg.nextDestination();
986                    try {
987                        _nucleus.sendMessage(msg);
988                    } catch (Exception ee) {
989                        _log.warn("Couldn't forward PingMessage : "+ee);
990                    }
991                } else {
992                    UOID uoid = msg.getUOID();
993                    EventLogger.deliverBegin(msg);
994                    try {
995                        messageToForward(msg);
996                    } finally {
997                        EventLogger.deliverEnd(msg.getSession(), uoid);
998                    }
999                }
1000            }
1001        }
1002 
1003    }
1004    private Object executeLocalCommand(Object command)
1005        throws CommandException  {
1006        //      _log.info("executeLocalCommand() : "+command.getClass().getName()+" [_returnCommandException="+_returnCommandException);
1007        if (command instanceof Authorizable) {
1008 
1009            if (_returnCommandException) {
1010                try {
1011                    return command(new AuthorizedArgs((Authorizable)command));
1012                } catch (CommandException ce) {
1013                    throw ce;
1014                } catch (Throwable xe) {
1015                    throw new CommandException(1, "Unknown : "+xe.toString());
1016                }
1017            } else {
1018                return autoCommand(command);
1019            }
1020 
1021        } else if (command instanceof String) {
1022 
1023            if (_returnCommandException) {
1024                try {
1025                    return command(new Args((String)command));
1026                } catch (CommandException ce) {
1027                    throw ce;
1028                } catch (Throwable xe) {
1029                    throw new CommandException(1, "Unknown : "+xe.toString());
1030                }
1031            } else {
1032                return autoCommand((String)command);
1033            }
1034 
1035        } else if (command instanceof CommandRequestable) {
1036            try {
1037                return command((CommandRequestable)command);
1038            } catch (CommandException ce) {
1039                throw ce;
1040            } catch (Throwable xe) {
1041                throw new CommandException(1,"Unknown : "+xe.toString());
1042            }
1043        } else
1044            throw new
1045                CommandPanicException("Illegal CommandClass detected",
1046                                      new Exception("PANIC"));
1047 
1048 
1049    }
1050    private Object autoCommand(Object command) {
1051 
1052        try {
1053            if (command instanceof String)
1054                return command(new Args((String)command));
1055            else if (command instanceof AuthorizedString)
1056                return command(new AuthorizedArgs((AuthorizedString)command));
1057            else
1058                return "Panic : internal server error 14345";
1059        } catch (CommandSyntaxException cse) {
1060            return commandArrived(command.toString(), cse);
1061        } catch (CommandExitException cee) {
1062            return "Sorry, can't exit";
1063        } catch (CommandThrowableException cte) {
1064            StringBuffer sb = new StringBuffer();
1065            sb.append(cte.getMessage()+"\n");
1066            Throwable t = cte.getTargetException();
1067            sb.append(t.getClass().getName()+" : "+t.getMessage()+"\n");
1068            return sb.toString();
1069        } catch (CommandPanicException cpe) {
1070            StringBuffer sb = new StringBuffer();
1071            sb.append("Panic : "+cpe.getMessage()+"\n");
1072            Throwable t = cpe.getTargetException();
1073            sb.append(t.getClass().getName()+" : "+t.getMessage()+"\n");
1074            return sb.toString();
1075        } catch (Exception e) {
1076            return "??? : "+e.toString();
1077        }
1078    }
1079    private CellPath _aclPath    = new CellPath("acm");
1080    private long     _aclTimeout = 10000L;
1081    protected void checkAclPermission(Authorizable auth, Object command, String [] acls) throws CommandException {
1082 
1083        String user = auth.getAuthorizedPrincipal();
1084 
1085        if (user.equals("admin") || (acls == null) || (acls.length == 0))return;
1086 
1087        CommandException recentException = null;
1088 
1089        for (int i = 0; i < acls.length; i++) {
1090            try {
1091                checkAclPermission(user, command, acls[i]);
1092                return;
1093            } catch (CommandAclException ce) {
1094                recentException = ce;
1095            }
1096        }
1097        throw recentException;
1098    }
1099    protected void checkAclPermission(String user, Object command,  String acl) throws CommandException {
1100 
1101        Object [] request = new Object[5];
1102 
1103        request[0] = "request";
1104        request[1] = "<nobody>";
1105        request[2] = "check-permission";
1106        request[3] = user;
1107        request[4] = acl;
1108 
1109        CellMessage reply = null;
1110 
1111        try {
1112            reply = _nucleus.sendAndWait(
1113                                         new CellMessage(_aclPath, request),
1114                                         _aclTimeout);
1115 
1116            if (reply == null)
1117                throw new
1118                    Exception("Acl Request timed out ("+_aclPath+")");
1119 
1120        } catch (Exception ee) {
1121            throw new
1122                CommandException("Error in acl handling : "+ee.getMessage());
1123        }
1124        Object r = reply.getMessageObject();
1125        if ((r == null) ||
1126            (! (r instanceof Object [])) ||
1127            (((Object [])r).length < 6) ||
1128            (! (((Object [])r)[5] instanceof Boolean)))
1129            throw new
1130                CommandException("Error in acl handling : illegal reply arrived");
1131 
1132        if (! (((Boolean)((Object [])r)[5]).booleanValue()))
1133            throw new
1134                CommandAclException(user, acl);
1135 
1136        return;
1137 
1138    }
1139}

[all classes][dmg.cells.nucleus]
EMMA 2.0.5312 (C) Vladimir Roubtsov