001 
002 /*
003  *  JScripter Standard 1.0 - To Script In Java
004  *  Copyright (C) 2008-2011  J.J.Liu<jianjunliu@126.com> <http://www.jscripter.org>
005  *  
006  *  This program is free software: you can redistribute it and/or modify
007  *  it under the terms of the GNU Affero General Public License as published by
008  *  the Free Software Foundation, either version 3 of the License, or
009  *  (at your option) any later version.
010  *  
011  *  This program is distributed in the hope that it will be useful,
012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014  *  GNU Affero General Public License for more details.
015  *  
016  *  You should have received a copy of the GNU Affero General Public License
017  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
018  */
019 
020 package jsx.http.rpc.remote;
021 
022 import js.ArrayLike;
023 import js.Initializer;
024 import js.Js;
025 import js.ObjectLike;
026 import js.Vars;
027 import jsx.Returnable;
028 import jsx.core.ArrayLikes;
029 
030 /**
031  * <p>A base class of the client-side providers for remote reflect services.</p>
032  * <p>Note that a client-side provider for remote reflect services is also a 
033  * {@link Remote} object.</p>
034  * 
035  * @author <a href="mailto:jianjunliu@126.com">J.J.Liu (Jianjun Liu)</a> at <a href="http://www.jscripter.org" target="_blank">http://www.jscripter.org</a>
036  */
037 public class Reflector extends RemoteReflector
038 {
039     /**
040      * <p>A typical constructor for a {@link Reflector} object.</p>
041      * @param o An initializer for configuration.
042      * @since 1.0
043      */
044     protected Reflector(ObjectLike o) {
045         super(o);
046     }
047 
048     /**
049      * <p>A typical constructor for a {@link Reflector} object.</p>
050      * @param url The resource locator for {@link Reflector} object being constructed.
051      * @since 1.0
052      */
053     public Reflector(String url) {
054         super(new Initializer().set(TID, TID_REFLECTOR).set(URL, url).var());
055     }
056 
057     /**
058      * <p>Synchronously registers the current reflector.</p>
059      * @return A registered version of this reflector.
060      * @since 1.0
061      */
062     @Override
063     public final Reflector register() {
064         return new Reflector((ObjectLike)call(
065                 url(),
066                 new Vars<Object>().add(REGISTER).var()
067         ));
068     }
069 
070     /**
071      * <p>Synchronously increases remote reference count for a remote object.</p>
072      * @param args An array of arguments. Only the first one is used here.
073      * @since 1.0
074      */
075     @Override
076     public final void increase(ArrayLike<Remote> args) {
077         call(url(), ArrayLikes.concat(
078                 new Vars<Object>().add(INCREASE).var(),
079                 args
080         ));
081     }
082 
083     /**
084      * <p>Synchronously decreases remote reference count for a remote object.</p>
085      * @param args An array of arguments. Only the first one is used here.
086      * @since 1.0
087      */
088     @Override
089     public final void decrease(ArrayLike<Remote> args) {
090         call(url(), ArrayLikes.concat(
091                 new Vars<Object>().add(DECREASE).var(),
092                 args
093         ));
094     }
095 
096     /**
097      * <p>Synchronously loads a remote class by the class name.</p>
098      * @param name A Java class name.
099      * @return The newly created remote class with the class name.
100      * @since 1.0
101      */
102     @Override
103     public Remote forName(String name) {
104         return new Remote((ObjectLike)call(
105                 url(),
106                 new Vars<Object>().add(FOR_NAME).add(name).var()
107         ));
108     }
109 
110     /**
111      * <p>Synchronously gets the remote class for a remote object.</p>
112      * @param o A remote object.
113      * @return The remote class for the remote object.
114      * @since 1.0
115      */
116     @Override
117     public Remote getRemoteClass(Remote o) {
118         return new Remote((ObjectLike)call(
119                 url(),
120                 new Vars<Object>().add(GET_REMOTE_CLASS).add(o).var()
121         ));
122     }
123 
124     /**
125      * <p>Synchronously creates a remote instance of a remote class.</p>
126      * @param o The remote class.
127      * @return The newly created remote object.
128      * @since 1.0
129      */
130     @Override
131     public Remote newInstance(Remote o) {
132         assertType(o, TID_CLASS);
133         return new Remote((ObjectLike)call(
134                 url(),
135                 new Vars<Object>().add(NEW_INSTANCE).add(o).var()
136         ));
137     }
138 
139     /**
140      * <p>Synchronously gets an element of a remote array.</p>
141      * @param o The remote array.
142      * @param i The array index for the element.
143      * @return A remote value or object.
144      * @since 1.0
145      */
146     @Override
147     public Remote getArrayElement(Remote o, int i) {
148         assertType(o, TID_ARRAY);
149         return new Remote((ObjectLike)call(
150                 url(),
151                 new Vars<Object>().add(GET_ARRAY_ELEMENT).add(o).add(i).var()
152         ));
153     }
154 
155     /**
156      * <p>Synchronously gets the current length of a remote array.</p>
157      * @param o The remote array.
158      * @return A remote value for the length.
159      * @since 1.0
160      */
161     @Override
162     public Remote getArrayLength(Remote o) {
163         assertType(o, TID_ARRAY);
164         return new Remote((ObjectLike)call(
165                 url(),
166                 new Vars<Object>().add(GET_ARRAY_LENGTH).add(o).var()
167         ));
168     }
169 
170     /**
171      * <p>Synchronously sets an element of a remote array.</p>
172      * @param o The remote array.
173      * @param i The array index for the element.
174      * @param v The new value for the element.
175      * @return A remote value or object.
176      * @since 1.0
177      */
178     @Override
179     public Remote setArrayElement(Remote o, int i, Remote v) {
180         assertType(o, TID_ARRAY);
181         return new Remote((ObjectLike)call(
182                 url(),
183                 new Vars<Object>().add(SET_ARRAY_ELEMENT).add(o).add(i).add(v).var()
184         ));
185     }
186 
187     /**
188      * <p>Synchronously gets a remote field.</p>
189      * @param o The remote object for the base.
190      * @param name The name for the field.
191      * @return A remote field.
192      * @since 1.0
193      */
194     @Override
195     public Remote getField(Remote o, String name) {
196         return new Remote((ObjectLike)call(
197                 url(),
198                 new Vars<Object>().add(GET_FIELD).add(o).add(name).var()
199         ));
200     }
201 
202     /**
203      * <p>Synchronously evaluates a remote static field.</p>
204      * @param o The remote static field.
205      * @return A remote value or object.
206      * @since 1.0
207      */
208     @Override
209     public Remote get(Remote o) {
210         assertType(o, TID_FIELD);
211         return new Remote((ObjectLike)call(
212                 url(),
213                 new Vars<Object>().add(GET).add(o).var()
214         ));
215     }
216 
217     /**
218      * <p>Synchronously evaluates a remote instance field.</p>
219      * @param o The remote instance field.
220      * @param base The remote object for the base.
221      * @return A remote value or object.
222      * @since 1.0
223      */
224     @Override
225     public Remote get(Remote o, Remote base) {
226         assertType(o, TID_FIELD);
227         assertObject(base);
228         return new Remote((ObjectLike)call(
229                 url(),
230                 new Vars<Object>().add(GET).add(o).add(base).var()
231         ));
232     }
233 
234     /**
235      * <p>Synchronously gets a remote method.</p>
236      * @param o The remote object for the base.
237      * @param name The name for the method.
238      * @return A remote method.
239      * @since 1.0
240      */
241     @Override
242     public Remote getMethod(Remote o, String name) {
243         return new Remote((ObjectLike)call(
244                 url(),
245                 new Vars<Object>().add(GET_METHOD).add(o).add(name).var()
246         ));
247     }
248 
249     /**
250      * <p>Synchronously gets a remote method.</p>
251      * @param o The remote object for the base.
252      * @param name The name for the method.
253      * @param types An array of argument types for the remote method.
254      * @return A remote method.
255      * @since 1.0
256      */
257     @Override
258     public Remote getMethod(Remote o, String name, ArrayLike<String> types) {
259         return new Remote((ObjectLike)call(
260                 url(),
261                 ArrayLikes.concat(
262                         new Vars<Object>().add(GET_METHOD).add(o).add(name).var(),
263                         types
264                 )
265         ));
266     }
267 
268     /**
269      * <p>Synchronously invokes a remote method without arguments.</p>
270      * @param o The remote method.
271      * @return A remote value or object returned from the remote method invocation.
272      * @since 1.0
273      */
274     @Override
275     public Remote invoke(Remote o) {
276         assertType(o, TID_METHOD);
277         return new Remote((ObjectLike)call(
278                 url(),
279                 new Vars<Object>().add(INVOKE).add(o).var()
280         ));
281     }
282 
283     /**
284      * <p>Synchronously invokes a remote method with arguments.</p>
285      * @param o The remote method.
286      * @param args An array of arguments.
287      * @return A remote value or object returned from the remote method invocation.
288      * @since 1.0
289      */
290     @Override
291     public Remote invoke(Remote o, ArrayLike<Remote> args) {
292         assertType(o, TID_METHOD);
293         return new Remote((ObjectLike)call(
294                 url(),
295                 ArrayLikes.concat(
296                         new Vars<Object>().add(INVOKE).add(o).var(),
297                         args
298                 )
299         ));
300     }
301 
302     /**
303      * <p>Asynchronously registers the current reflector.</p>
304      * @param rt A {@link Returnable} for this asynchronous call to return a registered 
305      * version of the current reflector.
306      * @since 1.0
307      */
308     public synchronized final void register(final Returnable<Reflector> rt) {
309         new Caller(url()) {
310             @Override
311             public void callback(Object ret) {
312                 if (Js.be(rt)) {
313                     rt.onReturn(new Reflector((ObjectLike)ret));
314                 }
315             }
316         }.call(new Vars<Object>().add(REGISTER).var());
317     }
318 
319     /**
320      * <p>Gets an asynchronous caller for this reflector with a given {@link Returnable}.</p>
321      * @param rt The {@link Returnable} for the asynchronous caller to return value 
322      * on the success of an invocation.
323      * @return An asynchronous caller.
324      * @since 1.0
325      */
326     protected final Caller getCaller(final Returnable<Remote> rt) {
327         return new Caller(url()) {
328             @Override
329             public void callback(Object ret) {
330                 if (Js.be(rt)) {
331                     rt.onReturn(new Remote((ObjectLike)ret));
332                 }
333             }
334         };
335     }
336 
337     /**
338      * <p>Asynchronously increases remote reference count for a remote object.</p>
339      * @param args An array of arguments. Only the first one is used here.
340      * @param rt A {@link Returnable} for this asynchronous call to return value.
341      * @since 1.0
342      */
343     public synchronized final void increase(ArrayLike<Remote> args, Returnable<Remote> rt) {
344         getCaller(rt).call(ArrayLikes.concat(
345                 new Vars<Object>().add(INCREASE).var(),
346                 args
347         ));
348     }
349 
350     /**
351      * <p>Asynchronously decreases remote reference count for a remote object.</p>
352      * @param args An array of arguments. Only the first one is used here.
353      * @param rt A {@link Returnable} for this asynchronous call to return value.
354      * @since 1.0
355      */
356     public synchronized final void decrease(ArrayLike<Remote> args, Returnable<Remote> rt) {
357         getCaller(rt).call(ArrayLikes.concat(
358                 new Vars<Object>().add(DECREASE).var(),
359                 args
360         ));
361     }
362 
363     /**
364      * <p>Asynchronously loads a remote class by the class name.</p>
365      * @param name A Java class name.
366      * @param rt A {@link Returnable} for this asynchronous call to return the newly 
367      * created remote class with the class name.
368      * @since 1.0
369      */
370     public synchronized final void forName(String name, Returnable<Remote> rt) {
371         getCaller(rt).call(new Vars<Object>().add(FOR_NAME).add(name).var());
372     }
373 
374     /**
375      * <p>Asynchronously gets the remote class for a remote object.</p>
376      * @param o A remote object.
377      * @param rt A {@link Returnable} for this asynchronous call to return the remote 
378      * class for the remote object.
379      * @since 1.0
380      */
381     public synchronized final void getRemoteClass(Remote o, Returnable<Remote> rt) {
382         getCaller(rt).call(new Vars<Object>().add(GET_REMOTE_CLASS).add(o).var());
383     }
384 
385     /**
386      * <p>Asynchronously creates a remote instance of a remote class.</p>
387      * @param o The remote class.
388      * @param rt A {@link Returnable} for this asynchronous call to return the newly 
389      * created remote object.
390      * @since 1.0
391      */
392     public synchronized final void newInstance(Remote o, Returnable<Remote> rt) {
393         assertType(o, TID_CLASS);
394         getCaller(rt).call(new Vars<Object>().add(NEW_INSTANCE).add(o).var());
395     }
396 
397     /**
398      * <p>Asynchronously gets an element of a remote array.</p>
399      * @param o The remote array.
400      * @param i The array index for the element.
401      * @param rt A {@link Returnable} for this asynchronous call to return value.
402      * @since 1.0
403      */
404     public synchronized final void getArrayElement(Remote o, int i, Returnable<Remote> rt) {
405         assertType(o, TID_ARRAY);
406         getCaller(rt).call(new Vars<Object>().add(GET_ARRAY_ELEMENT).add(o).add(i).var());
407     }
408 
409     /**
410      * <p>Asynchronously gets the current length of a remote array.</p>
411      * @param o The remote array.
412      * @param rt A {@link Returnable} for this asynchronous call to return value.
413      * @since 1.0
414      */
415     public synchronized final void getArrayLength(Remote o, Returnable<Remote> rt) {
416         assertType(o, TID_ARRAY);
417         getCaller(rt).call(new Vars<Object>().add(GET_ARRAY_LENGTH).add(o).var());
418     }
419 
420     /**
421      * <p>Asynchronously sets an element of a remote array.</p>
422      * @param o The remote array.
423      * @param i The array index for the element.
424      * @param v The new value for the element.
425      * @param rt A {@link Returnable} for this asynchronous call to return value.
426      * @since 1.0
427      */
428     public synchronized final void setArrayElement(Remote o, int i, Remote v, Returnable<Remote> rt) {
429         assertType(o, TID_ARRAY);
430         getCaller(rt).call(new Vars<Object>().add(SET_ARRAY_ELEMENT).add(o).add(i).add(v).var());
431     }
432 
433     /**
434      * <p>Asynchronously gets a remote field.</p>
435      * @param o The remote object for the base.
436      * @param name The name for the field.
437      * @param rt A {@link Returnable} for this asynchronous call to return a remote field.
438      * @since 1.0
439      */
440     public synchronized final void getField(Remote o, String name, Returnable<Remote> rt) {
441         getCaller(rt).call(new Vars<Object>().add(GET_FIELD).add(o).add(name).var());
442     }
443 
444     /**
445      * <p>Asynchronously evaluates a remote static field.</p>
446      * @param o The remote static field.
447      * @param rt A {@link Returnable} for this asynchronous call to return value.
448      * @since 1.0
449      */
450     public synchronized final void get(Remote o, Returnable<Remote> rt) {
451         assertType(o, TID_FIELD);
452         getCaller(rt).call(new Vars<Object>().add(GET).add(o).var());
453     }
454 
455     /**
456      * <p>Asynchronously evaluates a remote instance field.</p>
457      * @param o The remote instance field.
458      * @param base The remote object for the base.
459      * @param rt A {@link Returnable} for this asynchronous call to return value.
460      * @since 1.0
461      */
462     public synchronized final void get(Remote o, Remote base, Returnable<Remote> rt) {
463         assertType(o, TID_FIELD);
464         assertObject(base);
465         getCaller(rt).call(new Vars<Object>().add(GET).add(o).add(base).var());
466     }
467 
468     /**
469      * <p>Asynchronously gets a remote method.</p>
470      * @param o The remote object for the base.
471      * @param name The name for the method.
472      * @param rt A {@link Returnable} for this asynchronous call to return a remote method.
473      * @since 1.0
474      */
475     public synchronized final void getMethod(Remote o, String name, Returnable<Remote> rt) {
476         getCaller(rt).call(new Vars<Object>().add(GET_METHOD).add(o).add(name).var());
477     }
478 
479     /**
480      * <p>Asynchronously gets a remote method.</p>
481      * @param o The remote object for the base.
482      * @param name The name for the method.
483      * @param types An array of argument types for the remote method.
484      * @param rt A {@link Returnable} for this asynchronous call to return a remote method.
485      * @since 1.0
486      */
487     public synchronized final void getMethod(Remote o, String name, ArrayLike<String> types, final Returnable<Remote> rt) {
488         getCaller(rt).call(ArrayLikes.concat(
489                 new Vars<Object>().add(GET_METHOD).add(o).add(name).var(),
490                 types
491         ));
492     }
493 
494     /**
495      * <p>Asynchronously invokes a remote method without arguments.</p>
496      * @param o The remote method.
497      * @param rt A {@link Returnable} for this asynchronous call to return the remote value 
498      * or object returned from the remote method invocation.
499      * @since 1.0
500      */
501     public synchronized final void invoke(Remote o, Returnable<Remote> rt) {
502         assertType(o, TID_METHOD);
503         getCaller(rt).call(new Vars<Object>().add(INVOKE).add(o).var());
504     }
505 
506     /**
507      * <p>Asynchronously invokes a remote method with arguments.</p>
508      * @param o The remote method.
509      * @param args An array of arguments.
510      * @param rt A {@link Returnable} for this asynchronous call to return the remote value 
511      * or object returned from the remote method invocation.
512      * @since 1.0
513      */
514     public synchronized final void invoke(Remote o, ArrayLike<Remote> args, Returnable<Remote> rt) {
515         assertType(o, TID_METHOD);
516         getCaller(rt).call(ArrayLikes.concat(
517                 new Vars<Object>().add(INVOKE).add(o).var(),
518                 args
519         ));
520     }
521 }