001/*
002 * jPOS Project [http://jpos.org]
003 * Copyright (C) 2000-2026 jPOS Software SRL
004 *
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU Affero General Public License as
007 * published by the Free Software Foundation, either version 3 of the
008 * License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013 * GNU Affero General Public License for more details.
014 *
015 * You should have received a copy of the GNU Affero General Public License
016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017 */
018
019package org.jpos.q2.qbean;
020
021import bsh.EvalError;
022import bsh.Interpreter;
023import org.jdom2.Element;
024import org.jpos.core.ConfigurationException;
025import org.jpos.q2.QBeanSupport;
026import org.jpos.space.Space;
027import org.jpos.space.SpaceError;
028import org.jpos.space.SpaceFactory;
029import org.jpos.util.NameRegistrar;
030
031import java.io.IOException;
032import java.util.Iterator;
033
034@SuppressWarnings("unchecked")
035public class SpaceLet extends QBeanSupport implements Space {
036    Space sp;
037    String uri;
038    String outScript, outSource;
039    String pushScript, pushSource;
040    String inScript, inSource;
041    String rdScript, rdSource;
042    String putScript, putSource;
043
044    public void initService() throws ConfigurationException {
045        Element config = getPersist ();
046        grabSpace (config.getChild ("space"));
047        initSpace (config.getChild ("init"));
048
049        String name = getName();
050        if ("spacelet".equals (name))
051            name = "default";
052        uri = "spacelet:" + name;
053
054        Element e = config.getChild ("out");
055        outScript = getScript (e);
056        if (e != null)
057            outSource = e.getAttributeValue ("source");
058
059        e = config.getChild ("push");
060        pushScript = getScript (e);
061        if (e != null)
062            pushSource = e.getAttributeValue ("source");
063
064        e = config.getChild ("in");
065        inScript = getScript (e);
066        if (e != null)
067            inSource = e.getAttributeValue ("source");
068
069        e = config.getChild ("rd");
070        rdScript = getScript (e);
071        if (e != null)
072            rdSource = e.getAttributeValue ("source");
073
074        e = config.getChild ("put");
075        putScript = getScript (e);
076        if (e != null)
077            putSource = e.getAttributeValue ("source");
078
079    }
080    public void startService() {
081        NameRegistrar.register (uri, this);
082
083        Iterator iter = getPersist().getChildren("run").iterator();
084        while (iter.hasNext ()) 
085            launch ((Element) iter.next ());
086    }
087    public void stopService() {
088        NameRegistrar.unregister (uri);
089    }
090    public void out (Object key, Object value) {
091        try {
092            Interpreter bsh = initInterpreter (key, value);
093            synchronized (sp) {
094                if (!eval (bsh, outScript, outSource))
095                    sp.out (key, value);
096            }
097        } catch (Throwable t) {
098            throw new SpaceError (t);
099        }
100    }
101    public void out (Object key, Object value, long timeout) {
102        try {
103            Interpreter bsh = initInterpreter (key, value, timeout);
104            synchronized (sp) {
105                if (!eval (bsh, outScript, outSource))
106                    sp.out (key, value, timeout);
107            }
108        } catch (Throwable t) {
109            throw new SpaceError (t);
110        }
111    }
112    public void push (Object key, Object value) {
113        try {
114            Interpreter bsh = initInterpreter (key, value);
115            synchronized (sp) {
116                if (!eval (bsh, pushScript, pushSource))
117                    sp.out (key, value);
118            }
119        } catch (Throwable t) {
120            throw new SpaceError (t);
121        }
122    }
123    public void push (Object key, Object value, long timeout) {
124        try {
125            Interpreter bsh = initInterpreter (key, value, timeout);
126            synchronized (sp) {
127                if (!eval (bsh, pushScript, pushSource))
128                    sp.out (key, value, timeout);
129            }
130        } catch (Throwable t) {
131            throw new SpaceError (t);
132        }
133    }
134    public void put (Object key, Object value) {
135        try {
136            Interpreter bsh = initInterpreter (key, value);
137            synchronized (sp) {
138                if (!eval (bsh, putScript, putSource))
139                    sp.put (key, value);
140            }
141        } catch (Throwable t) {
142            throw new SpaceError (t);
143        }
144    }
145    public void put (Object key, Object value, long timeout) {
146        try {
147            Interpreter bsh = initInterpreter (key, value, timeout);
148            synchronized (sp) {
149                if (!eval (bsh, putScript, putSource))
150                    sp.out (key, value, timeout);
151            }
152        } catch (Throwable t) {
153            throw new SpaceError (t);
154        }
155    }
156
157
158    public Object in  (Object key) {
159        try {
160            Interpreter bsh = initInterpreter (key);
161            synchronized (sp) {
162                if (eval (bsh, inScript, inSource)) {
163                    return bsh.get ("value");
164                } else {
165                    return sp.in (key);
166                }
167            }
168        } catch (Throwable t) {
169            throw new SpaceError (t);
170        }
171    }
172    public Object rd  (Object key) {
173        try {
174            Interpreter bsh = initInterpreter (key);
175            synchronized (sp) {
176                if (eval (bsh, rdScript, rdSource)) {
177                    return bsh.get ("value");
178                } else {
179                    return sp.rd (key);
180                }
181            }
182        } catch (Throwable t) {
183            throw new SpaceError (t);
184        }
185    }
186    public Object in  (Object key, long timeout) {
187        try {
188            Interpreter bsh = initInterpreter (key, timeout);
189            synchronized (sp) {
190                if (eval (bsh, inScript, inSource)) {
191                    return bsh.get ("value");
192                } else {
193                    return sp.in (key, timeout);
194                }
195            }
196        } catch (Throwable t) {
197            throw new SpaceError (t);
198        }
199    }
200    public Object rd  (Object key, long timeout) {
201        try {
202            Interpreter bsh = initInterpreter (key, timeout);
203            synchronized (sp) {
204                if (eval (bsh, rdScript, rdSource)) {
205                    return bsh.get ("value");
206                } else {
207                    return sp.rd (key, timeout);
208                }
209            }
210        } catch (Throwable t) {
211            throw new SpaceError (t);
212        }
213    }
214    public Object inp (Object key) {
215        try {
216            Interpreter bsh = initInterpreter (key);
217            bsh.set ("probe", true);
218            synchronized (sp) {
219                if (eval (bsh, inScript, inSource)) {
220                    return bsh.get ("value");
221                } else {
222                    return sp.inp (key);
223                }
224            }
225        } catch (Throwable t) {
226            throw new SpaceError (t);
227        }
228    }
229    public Object rdp (Object key) {
230        try {
231            Interpreter bsh = initInterpreter (key);
232            bsh.set ("probe", true);
233            synchronized (sp) {
234                if (eval (bsh, rdScript, rdSource)) {
235                    return bsh.get ("value");
236                } else {
237                    return sp.rdp (key);
238                }
239            }
240        } catch (Throwable t) {
241            throw new SpaceError (t);
242        }
243    }
244    public boolean existAny (Object[] keys) {
245        return sp.existAny (keys);
246    }
247    public boolean existAny (Object[] keys, long timeout) {
248        return sp.existAny (keys, timeout);
249    }
250    private void grabSpace (Element e) {
251        sp = SpaceFactory.getSpace (e != null ? e.getText() : "");
252    }
253    private String getScript (Element e) {
254        return e == null ? null : e.getText();
255    }
256    public void nrd (Object key) {
257         sp.nrd(key);
258    }
259    public Object nrd (Object key, long timeout) {
260        return sp.nrd(key, timeout);
261    }
262    private void launch (Element e) {
263        // final Interpreter bsh = initInterpreter ();
264        final String script = e.getText();
265        final String source = e.getAttributeValue ("source");
266
267        new Thread ("SpaceLet-launch") {
268            public void run () {
269                try {
270                    eval (initInterpreter(), script, source);
271                } catch (Throwable t) {
272                    getLog().warn (t);
273                }
274            }
275        }.start ();
276    }
277    private void initSpace (Element e) throws ConfigurationException {
278        if (e == null)
279            return;
280
281        try {
282            eval (
283                initInterpreter(), 
284                e.getText(), 
285                e.getAttributeValue ("source")
286            );
287        } catch (Throwable t) {
288            throw new ConfigurationException (t);
289        }
290    }
291    private Interpreter initInterpreter () throws EvalError {
292        Interpreter bsh = new Interpreter ();
293        bsh.set ("sp", sp);
294        bsh.set ("spacelet", this); 
295        bsh.set ("log", getLog());
296        return bsh;
297    }
298    private Interpreter initInterpreter (Object key) throws EvalError {
299        Interpreter bsh = initInterpreter ();
300        bsh.set ("key", key);
301        return bsh;
302    }
303    private Interpreter initInterpreter (Object key, Object value) 
304        throws EvalError
305    {
306        Interpreter bsh = initInterpreter (key);
307        bsh.set ("value", value);
308        return bsh;
309    }
310    private Interpreter initInterpreter 
311        (Object key, Object value, long timeout) 
312        throws EvalError 
313    {
314        Interpreter bsh = initInterpreter (key, value);
315        bsh.set ("timeout", timeout);
316        return bsh;
317    }
318    private Interpreter initInterpreter (Object key, long timeout) 
319        throws EvalError
320    {
321        Interpreter bsh = initInterpreter (key);
322        bsh.set ("timeout", timeout);
323        return bsh;
324    }
325    private boolean eval (Interpreter bsh, String script, String source)
326        throws EvalError, IOException
327    {
328        boolean rc = false;
329        if (script != null) {
330            Object retValue = bsh.eval (script);
331            if (source != null)
332                retValue = bsh.source (source);
333            if (retValue instanceof Boolean) {
334                rc = (Boolean) retValue;
335            }
336        }
337        return rc;
338    }
339}
340