PackageManager.cpp
Go to the documentation of this file.
1 /*----------------------------------------------------------------------------*/
2 /* */
3 /* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved. */
4 /* Copyright (c) 2005-2009 Rexx Language Association. All rights reserved. */
5 /* */
6 /* This program and the accompanying materials are made available under */
7 /* the terms of the Common Public License v1.0 which accompanies this */
8 /* distribution. A copy is also available at the following address: */
9 /* http://www.ibm.com/developerworks/oss/CPLv1.0.htm */
10 /* */
11 /* Redistribution and use in source and binary forms, with or */
12 /* without modification, are permitted provided that the following */
13 /* conditions are met: */
14 /* */
15 /* Redistributions of source code must retain the above copyright */
16 /* notice, this list of conditions and the following disclaimer. */
17 /* Redistributions in binary form must reproduce the above copyright */
18 /* notice, this list of conditions and the following disclaimer in */
19 /* the documentation and/or other materials provided with the distribution. */
20 /* */
21 /* Neither the name of Rexx Language Association nor the names */
22 /* of its contributors may be used to endorse or promote products */
23 /* derived from this software without specific prior written permission. */
24 /* */
25 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
26 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
27 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
28 /* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
29 /* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
30 /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */
31 /* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */
32 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */
33 /* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
34 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
35 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
36 /* */
37 /*----------------------------------------------------------------------------*/
38 /******************************************************************************/
39 /* REXX Kernel */
40 /* */
41 /* Primitive Package management */
42 /* */
43 /******************************************************************************/
44 
45 #include "RexxCore.h"
46 #include "PackageManager.hpp"
47 #include "LibraryPackage.hpp"
48 #include "Interpreter.hpp"
49 #include "RexxNativeCode.hpp"
50 #include "DirectoryClass.hpp"
51 #include "ActivityManager.hpp"
52 #include "RoutineClass.hpp"
53 #include "RexxInternalApis.h"
54 #include "ProtectedObject.hpp"
55 #include "SecurityManager.hpp"
56 #include "WeakReferenceClass.hpp"
57 #include "RexxActivation.hpp"
58 #include "PackageClass.hpp"
59 
60 // this first set is the inital image set, which we preserve the references
61 // to in order to reset the package loads when the Rexx environment shuts down
66 
67 RexxDirectory *PackageManager::packages = OREF_NULL; // our loaded packages
68 RexxDirectory *PackageManager::packageRoutines = OREF_NULL; // table of functions loaded from packages
71 
72 /**
73  * Initialize the package manager global state.
74  */
76 {
77  packages = new_directory(); // create the tables for the manager
81  // load the internal library first
82  loadInternalPackage(OREF_REXX, rexxPackage);
83  loadLibrary(OREF_REXXUTIL); // load the rexxutil package automatically
84 }
85 
86 
87 /**
88  * Return the information that needs to be saved in the saved
89  * image.
90  *
91  * @return An array of the items added to the saved image.
92  */
94 {
95 
96  RexxArray *imageArray = new_array(IMAGE_ARRAY_SIZE);
97  imageArray->put(packages, IMAGE_PACKAGES);
100  imageArray->put(loadedRequires, IMAGE_REQUIRES);
101 
102  return imageArray;
103 }
104 
105 
106 /**
107  * Restore the saved image data.
108  *
109  * @param imageArray The array we placed in the save image originally.
110  */
112 {
113  // The memory manager is not initialized yet, so we just store the references
114  // at this point. A little later, we'll replace these with copies.
115  imagePackages = (RexxDirectory *)imageArray->get(IMAGE_PACKAGES);
119 }
120 
121 
122 /**
123  * Restore the saved image data to operational status
124  */
126 {
127  // we use copies of the image directories to avoid old-to-new image problems.
128  // this also allows us to restore the environment after interpreter shutdown
133 
134  for (HashLink i = packages->first(); packages->available(i); i = packages->next(i))
135  {
136  // get the next package
137  LibraryPackage *package = (LibraryPackage *)packages->value(i);
138  // not one of the internal packages, so reload.
139  if (!package->isInternal())
140  {
141  package->reload();
142  package->makeInternal(); // make this part of the persistent set now
143  }
144  else
145  {
146  // the only internal package is the Rexx one
147  package->reload(rexxPackage);
148  }
149  }
150 }
151 
152 
153 /**
154  * Normal live marking.
155  */
156 void PackageManager::live(size_t liveMark)
157 {
162 }
163 
164 /**
165  * Generalized live marking.
166  */
168 {
173 }
174 
175 
176 /**
177  * Resolve a named package, dynamically loading the package
178  * if not already in the table.
179  *
180  * @param name The name of the library associated with this package.
181  *
182  * @return A resolved package...throws an exception if the package
183  * is not loadable.
184  */
186 {
187  // have we already loaded this package?
188  // may need to bootstrap it up first.
189  LibraryPackage *package = loadLibrary(name);
190  if (package == NULL)
191  {
192  // this is an error
194  }
195  return package;
196 }
197 
198 
199 /**
200  * Attempt to load a library without raising an error. Returns
201  * a LibraryPackage object for the library if the load was successful.
202  *
203  * @param name The target library name.
204  *
205  * @return A LibraryPackage object for the library, or OREF_NULL if was
206  * not resolvable.
207  */
209 {
210  // have we already loaded this package?
211  // may need to bootstrap it up first.
212  LibraryPackage *package = (LibraryPackage *)packages->at(name);
213  if (package == NULL)
214  {
215  package = new LibraryPackage(name);
216  // add this to our package list.
217  packages->put((RexxObject *)package, name);
218  // now force the package to load.
219  if (!package->load())
220  {
221  // unable to load the library, so remove this and return NULL.
222  packages->remove(name);
223  return OREF_NULL;
224  }
225  }
226  return package;
227 }
228 
229 
230 /**
231  * Create a Native method from a registered package.
232  *
233  * @param packageName
234  * The name of the package the library is loaded from.
235  *
236  * @param methodName The name of the procedure to resolve from the package.
237  *
238  * @return A Native method that represents this package entry. Returns
239  * NULL if not found.
240  */
242 {
243  // have we already loaded this package?
244  // may need to bootstrap it up first.
245  LibraryPackage *package = getLibrary(packageName);
246 
247  // now see if this can be resolved.
248  return package->resolveMethod(methodName);
249 }
250 
251 
252 /**
253  * Quietly create a Native method from a registered package.
254  *
255  * @param packageName
256  * The name of the package the library is loaded from.
257  *
258  * @param methodName The name of the procedure to resolve from the package.
259  *
260  * @return A Native method that represents this package entry. Returns
261  * NULL if not found.
262  */
264 {
265  // have we already loaded this package?
266  // may need to bootstrap it up first.
267  LibraryPackage *package = loadLibrary(packageName);
268  // silently fail this if it couldn't load
269  if (package == OREF_NULL)
270  {
271  return OREF_NULL;
272  }
273 
274  // now see if this can be resolved.
275  return package->resolveMethod(methodName);
276 }
277 
278 
279 
280 /**
281  * Resolve a package function activator.
282  *
283  * @param function The function name.
284  * @param package The package/library name.
285  * @param procedure Procedure name. Only used if directly loaded from a library
286  * file.
287  *
288  * @return A function activator for this function, if it can be
289  * resolved.
290  */
292 {
293  // see if we have this one already
294  RoutineClass *func = (RoutineClass *)registeredRoutines->at(function);
295 
296  // if we have this, then we can return it directly.
297  if (func != OREF_NULL)
298  {
299  return func;
300  }
301 
302  const char *functionName = function->getStringData();
303  const char *libraryName = packageName->getStringData();
304  const char *procedureName = procedure->getStringData();
305 
306  {
307  UnsafeBlock releaser; // don't hold the block while making the API call
308  // go register this (unconditionally....at this point, we don't care if this fails)
309  RexxRegisterFunctionDll(functionName, libraryName, procedureName);
310  }
311 
312 
313  // resolve a registered entry, if we can and add it to the cache
314  return createRegisteredRoutine(function);
315 }
316 
317 
318 /**
319  * Resolve a registered function.
320  *
321  * @param function The function name.
322  *
323  * @return A function activator for this function, if it can be
324  * resolved.
325  */
327 {
328  // see if we have this one already as a package function
329  RoutineClass *func = getLoadedRoutine(function);
330 
331  // if we have this, then we can return it directly.
332  if (func != OREF_NULL)
333  {
334  return func;
335  }
336 
337  // resolve a registered entry, if we can and add it to the cache
338  return createRegisteredRoutine(function);
339 }
340 
341 
342 /**
343  * Resolve a package function. This goes explicitly to a loaded
344  * package to resolve the name rather than relying on the global
345  * cache. This will resolve to the same routine object as the
346  * global cache, but this prevents us from picking one a
347  * different one in case of a name conflict.
348  *
349  * @param packageName
350  * The package name.
351  * @param function The function name.
352  *
353  * @return A routine object for this function.
354  */
356 {
357  // have we already loaded this package?
358  // may need to bootstrap it up first.
359  LibraryPackage *package = getLibrary(packageName);
360 
361  // now see if this can be resolved.
362  return package->resolveRoutine(function);
363 }
364 
365 
366 /**
367  * Quietly load a package function. This goes explicitly to a
368  * loaded package to resolve the name rather than relying on the
369  * global cache. This will resolve to the same routine object
370  * as the global cache, but this prevents us from picking one a
371  * different one in case of a name conflict.
372  *
373  * @param packageName
374  * The package name.
375  * @param function The function name.
376  *
377  * @return A routine object for this function.
378  */
380 {
381  // have we already loaded this package?
382  // may need to bootstrap it up first.
383  LibraryPackage *package = loadLibrary(packageName);
384  if (package == OREF_NULL)
385  {
386  return OREF_NULL;
387  }
388 
389  // now see if this can be resolved.
390  return package->resolveRoutine(function);
391 }
392 
393 
394 
395 /**
396  * Locate an already loaded function.
397  *
398  * @param function The function name.
399  *
400  * @return A function activator for this function, if it can be
401  * resolved.
402  */
404 {
405  // see if we have this one already as a package function
406  RoutineClass *func = (RoutineClass *)packageRoutines->at(function);
407 
408  // if we have this, then we can return it directly.
409  if (func != OREF_NULL)
410  {
411  return func;
412  }
413 
414  // see if we have this one already as a registered function
415  return (RoutineClass *)registeredRoutines->at(function);
416 }
417 
418 
419 /**
420  * Create a new registered function entry and add to the
421  * function cache.
422  *
423  * @param function
424  *
425  * @return
426  */
428 {
429  REXXPFN entry = NULL;
430 
431  const char *functionName = function->getStringData();
432 
433  {
434  UnsafeBlock releaser; // don't hold the lock while calling
435  // now go resolve this entry pointer
436  RexxResolveRoutine(functionName, &entry);
437  }
438 
439  // this is a failure
440  if (entry == NULL)
441  {
442  return OREF_NULL;
443  }
444 
445  // create a code handler and add to the cache
446  RoutineClass *func = new RoutineClass(function, new RegisteredRoutine(function, (RexxRoutineHandler *)entry));
447  function = function->upper();
448  ProtectedObject p(function);
449  registeredRoutines->put(func, function);
450  // we got this
451  return func;
452 }
453 
454 
455 /**
456  * Load an internal package into our list. This does not
457  * load a library, but links package routines ones already
458  * contained inside the interpreter.
459  *
460  * @param name Name of the package...this is probably "REXX" or "REXXUTIL".
461  * @param p The package descriptor with the method and function list.
462  */
464 {
465  // load up the package and add it to our cache
466  LibraryPackage *package = new LibraryPackage(name, p);
467  // have we already loaded this package?
468  packages->put((RexxObject *)package, name);
469  // now process the package loading after we add this to the table.
470  // This avoids a multi-threaded race condition resulting from the fact
471  // we release the global resource lock when we call out to the package loader.
472  package->loadPackage();
473 }
474 
475 
476 /**
477  * Register an in-process library package.
478  *
479  * @param name The name to register under.
480  * @param p The package table information.
481  *
482  * @return true if this was successfully registered, false if a package
483  * is already registered under the name.
484  */
486 {
487  // don't replace any already loaded packages
488  if (packages->at(name) != OREF_NULL)
489  {
490  return false;
491  }
492  // handle like an internal package
493  loadInternalPackage(name, p);
494  return true;
495 }
496 
497 
498 
499 /**
500  * Add a function to the package-defined functions table.
501  *
502  * @param name The name of the function.
503  * @param func
504  */
506 {
507  packageRoutines->put(func, name);
508 }
509 
510 
511 /**
512  * Process the basics of RxFuncAdd(). This will return 0 if the function can be
513  * resolved and is callable, 1 otherwise. If the target function is not in a
514  * loadable package file, this will also do the global registration.
515  *
516  * @param name The name of the registered function.
517  * @param module The name of the library containing the function.
518  * @param proc The target procedure name (ignored if the target library
519  * is a self-loading one).
520  *
521  * @return 0 if the function registration worked and the function is callable.
522  * 1 otherwise.
523  *
524  * @remarks Note that we return TheFalseObject (0) if the function is resolved
525  * and callable and TheTrueObject (1) for failure. This is because
526  * RxFuncAdd() directly returns this result. RxFuncAdd() is documented
527  * to return 0 on success and 1 on failure.
528  */
530 {
531  // make sure we're using uppercase name versions here.
532  name = name->upper();
533  ProtectedObject p1(name);
534 
535  // see if we have this one already, either from a package or previously loaded
536  RoutineClass *func = getLoadedRoutine(name);
537 
538  // if we have this, then we can return it directly.
539  if (func != OREF_NULL)
540  {
541  return TheFalseObject;
542  }
543 
544  // see if this package is resolveable/loadable.
545  LibraryPackage *package = loadLibrary(module);
546  if (package != OREF_NULL)
547  {
548  // See if this is resolvable in this context. If we got it,
549  // return 0, the false object.
551  }
552 
553  // ok, this is not a converted new-style package. Now try registering the function and
554  // resolving it in this process. This will also add this to the local cache
555  return resolveRoutine(name, module, proc) != OREF_NULL ? TheFalseObject : TheTrueObject;
556 }
557 
558 
559 /**
560  * Drop a registered function.
561  *
562  * @param name Name of the registered function.
563  *
564  * @return True if this was deregistered from the global table, false
565  * otherwise.
566  */
568 {
569  // we register this using the uppercase name, so make sure we uppercase it
570  // before looking in the tables.
571  name = name->upper();
572  ProtectedObject p(name);
573  // remove this from the local cache, then remove it from the global function
574  // registration.
575  registeredRoutines->remove(name);
576  const char *functionName = name->getStringData();
577 
578  {
579  UnsafeBlock releaser;
580  // if this is a registered routine, removed it from the registered table
581  registeredRoutines->remove(name);
582  // just allow this to pass through to Rexxapi. If this was truely registered
583  // instead of loaded implicitly, this will remove the entry. Otherwise, it will
584  // return false.
585  return RexxDeregisterFunction(functionName) == 0 ? TheFalseObject : TheTrueObject;
586  }
587 }
588 
589 
590 /**
591  * The query method backing RxFuncQuery(). This checks both
592  * our local tables and the global tables to see if something
593  * has been registered.
594  *
595  * @param name Target name.
596  *
597  * @return True if the external function exists in our local tables or
598  * in the global registry.
599  */
601 {
602  // we register this using the uppercase name, so make sure we uppercase it
603  // before looking in the tables.
604  name = name->upper();
605  ProtectedObject p(name);
606  // does this name exist in our table?
607  if (getLoadedRoutine(name) != OREF_NULL)
608  {
609  return TheFalseObject;
610  }
611 
612  const char *functionName = name->getStringData();
613  {
614  UnsafeBlock releaser;
615  // just allow this to pass through to Rexxapi. If this was truly registered
616  // instead of loaded implicitly, it will find it.
617  return RexxQueryFunction(functionName) != 0 ? TheTrueObject : TheFalseObject;
618  }
619 }
620 
621 
622 /**
623  * Unload all of the libraries loaded in this Rexx process.
624  */
626 {
627  // traverse the package table, and force an unload for each library we've loaded up.
628  for (HashLink i = packages->first(); packages->available(i); i = packages->next(i))
629  {
630  // get the next package
631  LibraryPackage *package = (LibraryPackage *)packages->value(i);
632  package->unload();
633  }
634 
635  // now roll back to a copy of the image versions of these directories so we only
636  // have the orignal image set once again
641 }
642 
643 
644 /**
645  * Attempt to call a native code function. This will call either
646  * new-style package functions or old-style registered functions.
647  *
648  * @param activity The activity we're running under.
649  * @param name The target name of the routine.
650  * @param arguments The function arguments.
651  * @param argcount The argument count.
652  * @param result The return result.
653  *
654  * @return true if we located and successfully called this function. false
655  * means the function is not located as a native function.
656  */
658  RexxObject **arguments, size_t argcount, size_t named_argcount, ProtectedObject &result)
659 {
660  // all of our tables use uppercase names...make this a case-insensitive lookup
661  name = name->upper();
662  ProtectedObject p(name);
663 
664  // package functions come first
665  RoutineClass *function = (RoutineClass *)packageRoutines->at(name);
666  if (function != OREF_NULL)
667  {
668  function->call(activity, name, arguments, argcount, named_argcount, result);
669  return true;
670  }
671 
672  // now check for registered functions. This will either return a cached value,
673  // or resolve a routine for the first time and return the cached value.
674  function = resolveRoutine(name);
675  if (function != OREF_NULL)
676  {
677  function->call(activity, name, arguments, argcount, named_argcount, result);
678  return true;
679  }
680 
681  // not one of these
682  return false;
683 }
684 
685 
686 /**
687  * Retrieve a ::REQUIRES file. This will cache the entries so
688  * that the same requires entry is returned for every request.
689  *
690  * @param activity The current activity.
691  * @param shortName The short name of the package.
692  * @param resolvedName
693  * The fully resolved name of a potential package file. The short
694  * name is used for checking in the MacroSpace, the long name
695  * is used for file searches.
696  * @param result The return package routine.
697  *
698  * @return The package routine (also returned in the result protected object).
699  */
701 {
702  result = OREF_NULL;
703 
704  SecurityManager *manager = activity->getEffectiveSecurityManager();
705  RexxObject *securityManager = OREF_NULL;
706 
707  shortName = manager->checkRequiresAccess(shortName, securityManager);
708  // no return means forbidden access to this name. Just return
709  // nothing
710  if (shortName == OREF_NULL)
711  {
712  return OREF_NULL;
713  }
714 
715 
716  // first check this using the specified name. Since we need to perform checks in the
717  // macro space, it's possible this will be loaded under the simple name. We'll need to check
718  // table again using the fully resolved name afterward.
719 
720  RoutineClass *package = checkRequiresCache(shortName, result);
721  if (package != OREF_NULL)
722  {
723  return package;
724  }
725 
726  unsigned short macroPosition; // a macrospace position marker
727 
728  // we need to look in the macrospace before we try checking for a file-based
729  // requires. The macrospace version uses the original name for all checks. Once we
730  // get to the file-based version, we switch to the full resolved name.
731  bool checkMacroSpace = RexxQueryMacro(shortName->getStringData(), &macroPosition) == 0;
732  if (checkMacroSpace && (macroPosition == RXMACRO_SEARCH_BEFORE))
733  {
734  return getMacroSpaceRequires(activity, shortName, result, securityManager);
735  }
736 
737  // it's possible we don't have a file version of this
738  if (resolvedName != OREF_NULL)
739  {
740  resolvedName = manager->checkRequiresAccess(resolvedName, securityManager);
741  // no return means forbidden access to this name. Just return
742  // nothing
743  if (resolvedName == OREF_NULL)
744  {
745  return OREF_NULL;
746  }
747 
748 
749  // now check again using the longer name
750  package = checkRequiresCache(resolvedName, result);
751  if (package != OREF_NULL)
752  {
753  return package;
754  }
755 
756  // load the file version of this.
757  return getRequiresFile(activity, resolvedName, securityManager, result);
758  }
759 
760  // do the macrospace after checks
761  if (checkMacroSpace)
762  {
763  return getMacroSpaceRequires(activity, shortName, result, securityManager);
764  }
765 
766  // nothing to return
767  return OREF_NULL;
768 }
769 
770 
771 /**
772  * Retrieve a ::REQUIRES file from the macrospace.
773  *
774  * @param activity The current activity.
775  * @param name The target name.
776  * @param result The returned Routine object for the package.
777  * @param securityManager
778  * A security manager to associated with the package.
779  *
780  * @return The located ::REQUIRES file.
781  */
783 {
784  // make sure we're not stuck in a circular reference
785  activity->checkRequires(name);
786  // unflatten the method and protect it
788  result = code;
789 
790  if (securityManager == OREF_NULL)
791  {
792  code->setSecurityManager(securityManager);
793  }
794  // we place the code in the package table so we have
795  // access to it to run the prologue code in other instances
796  // We also add this before running the prolog in case another
797  // thread tries to load the same thing.
798  WeakReference *ref = new WeakReference(code);
799  loadedRequires->put(ref, name);
800 
801  return code;
802 }
803 
804 
805 /**
806  * Retrieve a file version of a ::REQUIRES file.
807  *
808  * @param activity The current activity.
809  * @param name The fully resolved file name.
810  * @param result The return routine object.
811  *
812  * @return The return Routine instance.
813  */
815 {
816  // make sure we're not stuck in a circular reference
817  activity->checkRequires(name);
818  // try to load this from a previously compiled source file or
819  // translate it a new if not.
820  RoutineClass *code = RoutineClass::fromFile(name);
821  result = code; // we need to protect this until things are fully resolved.
822 
823  if (securityManager == OREF_NULL)
824  {
825  code->setSecurityManager(securityManager);
826  }
827  return code;
828 }
829 
830 
831 /**
832  * Loade a requires file from an in-store source. NOTE: This
833  * is not cached like the other requires files
834  *
835  * @param activity The current activity.
836  * @param name The fully resolved file name.
837  * @param result The return routine object.
838  *
839  * @return The return Routine instance.
840  */
841 RoutineClass *PackageManager::loadRequires(RexxActivity *activity, RexxString *name, const char *data, size_t length, ProtectedObject &result)
842 {
843  // first check this using the specified name.
844  RoutineClass *resolved = checkRequiresCache(name, result);
845  if (resolved != OREF_NULL)
846  {
847  return resolved;
848  }
849 
850  RoutineClass *code = new RoutineClass(name, data, length);
851  result = code;
852 
853  // we place the code in the package table so we have
854  // access to it to run the prologue code in other instances
855  // We also add this before running the prolog in case another
856  // thread tries to load the same thing.
857  WeakReference *ref = new WeakReference(code);
858  loadedRequires->put(ref, name);
859  return code;
860 }
861 
862 
863 /**
864  * Loade a requires file from an array source. NOTE: This is
865  * not cached like the other requires files
866  *
867  * @param activity The current activity.
868  * @param name The fully resolved file name.
869  * @param result The return routine object.
870  *
871  * @return The return Routine instance.
872  */
874 {
875  // first check this using the specified name.
876  RoutineClass *code = checkRequiresCache(name, result);
877  if (code == OREF_NULL)
878  {
879  code = new RoutineClass(name, data);
880  result = code;
881 
882  // we place the code in the package table so we have
883  // access to it to run the prologue code in other instances
884  // We also add this before running the prolog in case another
885  // thread tries to load the same thing.
886  WeakReference *ref = new WeakReference(code);
887  loadedRequires->put(ref, name);
888  }
889  return code;
890 }
891 
892 
893 /**
894  * Check for a package already in the requires cache.
895  *
896  * @param name The name of the target.
897  *
898  * @return The PackageClass instance, if any.
899  */
901 {
902  // first check this using the specified name. Since we need to perform checks in the
903  // macro space, it's possible this will be loaded under the simple name. We'll need to check
904  // table again using the fully resolved name afterward.
905  WeakReference *requiresRef = (WeakReference *)loadedRequires->get(name);
906  if (requiresRef != OREF_NULL)
907  {
908  RoutineClass *resolved = (RoutineClass *)requiresRef->get();
909  if (resolved != OREF_NULL)
910  {
911  result = resolved;
912  return resolved;
913  }
914  // this was garbage collected, remove it from the table
915  loadedRequires->remove(name);
916  }
917  return OREF_NULL;
918 }
919 
920 
921 /**
922  * Resolve an entry point for a package method entry (used on a
923  * restore or reflatten);
924  *
925  * @param name Name of the target method.
926  *
927  * @return The target entry point.
928  */
930 {
931  LibraryPackage *package = loadLibrary(packageName);
932 
933  // if no entry, something bad has gone wrong
934  if (package == NULL)
935  {
937  }
938  return package->resolveMethodEntry(name);
939 }
940 
941 
942 /**
943  * Resolve an entry point for a package function entry (used on
944  * a restore or reflatten);
945  *
946  * @param name Name of the target function.
947  *
948  * @return The target entry point.
949  */
951 {
952  LibraryPackage *package = loadLibrary(packageName);
953 
954  // if no entry, something bad has gone wrong
955  if (package == NULL)
956  {
958  }
959  return package->resolveRoutineEntry(name);
960 }
961 
962 
963 /**
964  * Resolve an entry point for a package function entry (used on
965  * a restore or reflatten);
966  *
967  * @param name Name of the target function.
968  *
969  * @return The target entry point.
970  */
972 {
973  // if there's no package name, then this is stored in raw name form (I don't believe this should
974  // ever happen....but.
975  if (packageName == OREF_NULL)
976  {
977  REXXPFN entry = NULL;
978 
979  const char *functionName = name->getStringData();
980  {
981  UnsafeBlock releaser;
982  // now go resolve this entry pointer
983  RexxResolveRoutine(functionName, &entry);
984  }
985 
986  // this is a failure
987  if (entry == NULL)
988  {
990  }
991  return (PREGISTEREDROUTINE)entry;
992  }
993  else
994  {
995  LibraryPackage *package = loadLibrary(packageName);
996 
997  // if no entry, something bad has gone wrong
998  if (package == NULL)
999  {
1001  }
1002  return package->resolveRegisteredRoutineEntry(name);
1003  }
1004 }
void reportException(wholenumber_t error)
RexxArray * new_array(size_t s)
Definition: ArrayClass.hpp:259
RexxDirectory * new_directory()
size_t(RexxEntry * PREGISTEREDROUTINE)(const char *, size_t, PCONSTRXSTRING, const char *, PRXSTRING)
uint16_t *(RexxEntry * PNATIVEMETHOD)(RexxMethodContext *, ValueDescriptor *)
uint16_t *(RexxEntry * PNATIVEROUTINE)(RexxCallContext *, ValueDescriptor *)
#define OREF_NULL
Definition: RexxCore.h:61
#define TheTrueObject
Definition: RexxCore.h:196
#define TheFalseObject
Definition: RexxCore.h:195
#define Error_Execution_library
#define Error_Execution_library_method
#define Error_Execution_library_routine
size_t HashLink
int REXXENTRY RexxResolveRoutine(const char *, REXXPFN *)
#define memory_mark(oref)
Definition: RexxMemory.hpp:450
#define memory_mark_general(oref)
Definition: RexxMemory.hpp:451
RoutineClass * resolveRoutine(RexxString *name)
RexxNativeMethod * resolveMethod(RexxString *name)
static RexxObject * dropRegisteredRoutine(RexxString *name)
static RexxDirectory * imagePackageRoutines
static RexxDirectory * registeredRoutines
static RoutineClass * resolveRoutine(RexxString *function, RexxString *packageName, RexxString *procedure)
static PNATIVEROUTINE resolveRoutineEntry(RexxString *package, RexxString *name)
static RoutineClass * getMacroSpaceRequires(RexxActivity *activity, RexxString *name, ProtectedObject &result, RexxObject *securityManager)
static void liveGeneral(int reason)
static bool callNativeRoutine(RexxActivity *activity, RexxString *name, RexxObject **arguments, size_t argcount, size_t named_argcount, ProtectedObject &result)
static void live(size_t liveMark)
static RexxDirectory * imageLoadedRequires
static RexxArray * getImageData()
static RexxDirectory * packageRoutines
static void addPackageRoutine(RexxString *name, RoutineClass *func)
static RoutineClass * loadRequires(RexxActivity *activity, RexxString *shortName, RexxString *resolvedName, ProtectedObject &result)
static RexxObject * queryRegisteredRoutine(RexxString *name)
static RexxPackageEntry * rexxPackage
static PREGISTEREDROUTINE resolveRegisteredRoutineEntry(RexxString *package, RexxString *name)
static RexxNativeMethod * loadMethod(RexxString *packageName, RexxString *methodName)
static RexxDirectory * imagePackages
static void unload()
static PNATIVEMETHOD resolveMethodEntry(RexxString *package, RexxString *name)
static LibraryPackage * loadLibrary(RexxString *name)
static void restore()
static RexxDirectory * loadedRequires
static RexxDirectory * packages
static void initialize()
static RoutineClass * checkRequiresCache(RexxString *name, ProtectedObject &result)
static bool registerPackage(RexxString *name, RexxPackageEntry *p)
static RexxDirectory * imageRegisteredRoutines
static LibraryPackage * getLibrary(RexxString *name)
static RexxNativeMethod * resolveMethod(RexxString *packageName, RexxString *methodName)
static void loadInternalPackage(RexxString *name, RexxPackageEntry *p)
static RoutineClass * getLoadedRoutine(RexxString *function)
static RoutineClass * getRequiresFile(RexxActivity *activity, RexxString *name, RexxObject *securityManager, ProtectedObject &result)
static RexxObject * addRegisteredRoutine(RexxString *name, RexxString *module, RexxString *proc)
static RoutineClass * loadRoutine(RexxString *packageName, RexxString *function)
static RoutineClass * createRegisteredRoutine(RexxString *function)
static RoutineClass * getMacroCode(RexxString *macroName)
SecurityManager * getEffectiveSecurityManager()
bool checkRequires(RexxString *n)
void put(RexxObject *eref, size_t pos)
Definition: ArrayClass.cpp:208
RexxObject * get(size_t pos)
Definition: ArrayClass.hpp:203
RexxObject * copy()
RexxObject * at(RexxString *)
RexxObject * put(RexxObject *, RexxString *)
RexxObject * remove(RexxString *)
bool available(HashLink pos)
HashLink next(HashLink pos)
virtual RexxObject * get(RexxObject *key)
const char * getStringData()
RexxString * upper()
RexxObject * setSecurityManager(RexxObject *)
static RoutineClass * fromFile(RexxString *filename)
RexxString * checkRequiresAccess(RexxString *name, RexxObject *&securityManager)
RexxObject * get()
RexxReturnCode REXXENTRY RexxDeregisterFunction(CONSTANT_STRING)
size_t REXXENTRY RexxRoutineHandler(CONSTANT_STRING, size_t, PCONSTRXSTRING, CONSTANT_STRING, PRXSTRING)
Definition: rexx.h:408
RexxReturnCode REXXENTRY RexxQueryFunction(CONSTANT_STRING)
RexxReturnCode REXXENTRY RexxRegisterFunctionDll(CONSTANT_STRING, CONSTANT_STRING, CONSTANT_STRING)
RexxReturnCode REXXENTRY RexxQueryMacro(CONSTANT_STRING, unsigned short *)
#define RXMACRO_SEARCH_BEFORE
Definition: rexxapidefs.h:220
Definition: oorexxapi.h:242
void * REXXPFN