• Publicity: Public Only All

apm-procs.tcl

Routines used by the package manager.

Location:
packages/acs-tcl/tcl/apm-procs.tcl
Created:
13 Apr 2000
Authors:
Bryan Quinn <bquinn@arsdigita.com>
Jon Salz <jsalz@arsdigita.com>
CVS Identification:
$Id: apm-procs.tcl,v 1.118 2024/10/08 14:13:36 antoniop Exp $

Procedures in this file

Detailed information

apm::convert_type (public)

 apm::convert_type -package_id package_id \
    -old_package_key old_package_key -new_package_key new_package_key

Convert a package instance to a new type, doing the proper instantiate and mount callbacks and parameter creation.

Switches:
-package_id (required)
The package instance to convert.
-old_package_key (required)
The package key we're converting from.
-new_package_key (required)
The new subsite type we're converting to.

Partial Call Graph (max 5 caller/called nodes):
%3 packages/acs-subsite/www/admin/subsite-convert-type.tcl packages/acs-subsite/ www/admin/subsite-convert-type.tcl apm::convert_type apm::convert_type packages/acs-subsite/www/admin/subsite-convert-type.tcl->apm::convert_type apm_invoke_callback_proc apm_invoke_callback_proc (public) apm::convert_type->apm_invoke_callback_proc apm_package_inherit_order apm_package_inherit_order (public) apm::convert_type->apm_package_inherit_order apm_parameter_sync apm_parameter_sync (public) apm::convert_type->apm_parameter_sync db_1row db_1row (public) apm::convert_type->db_1row db_dml db_dml (public) apm::convert_type->db_dml

Testcases:
No testcase defined.

apm::get_package_descendent_options (public)

 apm::get_package_descendent_options package_key

Get a list of pretty name, package key pairs for all packages which are descendents of the given package key.

Parameters:
package_key (required)
The parent package's key.
Returns:
a list of pretty name, package key pairs suitable for use in a template select widget.

Partial Call Graph (max 5 caller/called nodes):
%3 packages/acs-subsite/www/admin/index.tcl packages/acs-subsite/ www/admin/index.tcl apm::get_package_descendent_options apm::get_package_descendent_options packages/acs-subsite/www/admin/index.tcl->apm::get_package_descendent_options packages/acs-subsite/www/admin/subsite-convert-type.tcl packages/acs-subsite/ www/admin/subsite-convert-type.tcl packages/acs-subsite/www/admin/subsite-convert-type.tcl->apm::get_package_descendent_options apm_package_descendents apm_package_descendents (public) apm::get_package_descendent_options->apm_package_descendents db_list_of_lists db_list_of_lists (public) apm::get_package_descendent_options->db_list_of_lists

Testcases:
No testcase defined.

apm::metrics (public)

 apm::metrics -package_key package_key -file_type file_type \
    [ -array array ]

Return some code metrics about the files in package $package_key. This will return an array or dict containing at least the following items:

  • count - the number of files
  • lines - the number of lines in the files
  • blank_lines - the number of blank lines in the files
  • comment_lines - the number of blank lines in the files
  • procs - the number of procs, if applicable (0 if not applicable)

Valid file_type's:

  • data_model_pg - PG datamodel files
  • data_model_ora - Oracle datamodel files
  • include_page - ADP files in package_key/lib
  • content_page - ADP files in package_key/www
  • tcl_procs - Tcl procs in package_key/tcl
  • test_procs - automated tests in package_key/tcl/test
  • documentation - docs in package_key/www/doc
When the array is provided, it will be used for setting the result. Otherwise a dict with the metrics information is returned. This proc is cached.

Switches:
-package_key (required)
The package_key of interest
-file_type (required)
See options above
-array (optional)
variable to hold the array that will be returned
Author:
Vinod Kurup
Created:
2006-02-09

Partial Call Graph (max 5 caller/called nodes):
%3 apm::metrics_internal apm::metrics_internal (private) util_memoize util_memoize (public) apm::metrics apm::metrics apm::metrics->apm::metrics_internal apm::metrics->util_memoize

Testcases:
No testcase defined.

apm_application_new_checkbox (public)

 apm_application_new_checkbox

Return an HTML checkbox of package_key and package names for applications that can be mounted in the site-map. Excludes singletons that are already instantiated.

Author:
Peter Marklund

Partial Call Graph (max 5 caller/called nodes):
%3 packages/acs-subsite/www/admin/site-map/index.tcl packages/acs-subsite/ www/admin/site-map/index.tcl apm_application_new_checkbox apm_application_new_checkbox packages/acs-subsite/www/admin/site-map/index.tcl->apm_application_new_checkbox packages/acs-subsite/www/admin/site-map/site-map.tcl packages/acs-subsite/ www/admin/site-map/site-map.tcl packages/acs-subsite/www/admin/site-map/site-map.tcl->apm_application_new_checkbox packages/acs-subsite/www/site-map/index.tcl packages/acs-subsite/ www/site-map/index.tcl packages/acs-subsite/www/site-map/index.tcl->apm_application_new_checkbox acs_user::site_wide_admin_p acs_user::site_wide_admin_p (public) apm_application_new_checkbox->acs_user::site_wide_admin_p db_foreach db_foreach (public) apm_application_new_checkbox->db_foreach

Testcases:
No testcase defined.

apm_arg_names_for_callback_type (public)

 apm_arg_names_for_callback_type -type type

Return the list of required argument names for the given callback type.

Switches:
-type (required)
Author:
Peter Marklund

Partial Call Graph (max 5 caller/called nodes):
%3 test_acs_admin_require_site_wide acs_admin_require_site_wide (test acs-admin) apm_arg_names_for_callback_type apm_arg_names_for_callback_type test_acs_admin_require_site_wide->apm_arg_names_for_callback_type apm_callback_format_args apm_callback_format_args (public) apm_callback_format_args->apm_arg_names_for_callback_type apm_callback_has_valid_args apm_callback_has_valid_args (public) apm_callback_has_valid_args->apm_arg_names_for_callback_type packages/acs-admin/www/apm/version-callback-add-edit.tcl packages/acs-admin/ www/apm/version-callback-add-edit.tcl packages/acs-admin/www/apm/version-callback-add-edit.tcl->apm_arg_names_for_callback_type

Testcases:
acs_admin_require_site_wide

apm_assert_callback_type_supported (public)

 apm_assert_callback_type_supported type

Throw an error if the given callback type is not supported.

Parameters:
type (required)
Author:
Peter Marklund

Partial Call Graph (max 5 caller/called nodes):
%3 apm_get_callback_proc apm_get_callback_proc (public) apm_assert_callback_type_supported apm_assert_callback_type_supported apm_get_callback_proc->apm_assert_callback_type_supported apm_remove_callback_proc apm_remove_callback_proc (public) apm_remove_callback_proc->apm_assert_callback_type_supported apm_set_callback_proc apm_set_callback_proc (public) apm_set_callback_proc->apm_assert_callback_type_supported apm_callback_type_supported_p apm_callback_type_supported_p (public) apm_assert_callback_type_supported->apm_callback_type_supported_p apm_supported_callback_types apm_supported_callback_types (public) apm_assert_callback_type_supported->apm_supported_callback_types

Testcases:
No testcase defined.

apm_body_callback (public)

 apm_body_callback string

This callback uses the document API to append more text to the stream.

Parameters:
string (required)

Partial Call Graph (max 5 caller/called nodes):
%3

Testcases:
No testcase defined.

apm_build_one_package_relationships (public)

 apm_build_one_package_relationships package_key

Builds the nsv dependency structures for a single package.

Parameters:
package_key (required)

Partial Call Graph (max 5 caller/called nodes):
%3 apm_build_package_relationships apm_build_package_relationships (public) apm_build_one_package_relationships apm_build_one_package_relationships apm_build_package_relationships->apm_build_one_package_relationships apm_package_install apm_package_install (public) apm_package_install->apm_build_one_package_relationships packages/acs-admin/www/apm/package-add-2.tcl packages/acs-admin/ www/apm/package-add-2.tcl packages/acs-admin/www/apm/package-add-2.tcl->apm_build_one_package_relationships packages/acs-admin/www/apm/version-dependency-add-2.tcl packages/acs-admin/ www/apm/version-dependency-add-2.tcl packages/acs-admin/www/apm/version-dependency-add-2.tcl->apm_build_one_package_relationships packages/acs-admin/www/apm/version-dependency-remove.tcl packages/acs-admin/ www/apm/version-dependency-remove.tcl packages/acs-admin/www/apm/version-dependency-remove.tcl->apm_build_one_package_relationships apm_one_package_descendents apm_one_package_descendents (private) apm_build_one_package_relationships->apm_one_package_descendents apm_one_package_inherit_order apm_one_package_inherit_order (public) apm_build_one_package_relationships->apm_one_package_inherit_order apm_one_package_load_libraries_dependencies apm_one_package_load_libraries_dependencies (private) apm_build_one_package_relationships->apm_one_package_load_libraries_dependencies apm_package_list_url_resolution apm_package_list_url_resolution (public) apm_build_one_package_relationships->apm_package_list_url_resolution

Testcases:
No testcase defined.

apm_build_package_relationships (public)

 apm_build_package_relationships

Builds the nsv dependency and ancestor structures.

Partial Call Graph (max 5 caller/called nodes):
%3 packages/acs-bootstrap-installer/bootstrap.tcl packages/acs-bootstrap-installer/ bootstrap.tcl apm_build_package_relationships apm_build_package_relationships packages/acs-bootstrap-installer/bootstrap.tcl->apm_build_package_relationships apm_build_one_package_relationships apm_build_one_package_relationships (public) apm_build_package_relationships->apm_build_one_package_relationships apm_enabled_packages apm_enabled_packages (public) apm_build_package_relationships->apm_enabled_packages

Testcases:
No testcase defined.

apm_build_subsite_packages_list (public)

 apm_build_subsite_packages_list

Build the nsv_set cache of all packages which claim to implement subsite semantics. The kludge to add acs-subsite if it's not declared with the subsite attribute set true is needed during the upgrade process ...

Partial Call Graph (max 5 caller/called nodes):
%3 apm_package_install apm_package_install (public) apm_build_subsite_packages_list apm_build_subsite_packages_list apm_package_install->apm_build_subsite_packages_list packages/acs-admin/www/apm/package-add-2.tcl packages/acs-admin/ www/apm/package-add-2.tcl packages/acs-admin/www/apm/package-add-2.tcl->apm_build_subsite_packages_list packages/acs-bootstrap-installer/bootstrap.tcl packages/acs-bootstrap-installer/ bootstrap.tcl packages/acs-bootstrap-installer/bootstrap.tcl->apm_build_subsite_packages_list db_list db_list (public) apm_build_subsite_packages_list->db_list

Testcases:
No testcase defined.

apm_callback_and_log (public)

 apm_callback_and_log [ -severity severity ] callback message

Executes the $callback callback routine with $message as an argument, and calls ns_log with the given $severity.

Switches:
-severity (optional, defaults to "Notice")
Parameters:
callback (required)
message (required)

Partial Call Graph (max 5 caller/called nodes):
%3 test_upgrade upgrade (test acs-lang) apm_callback_and_log apm_callback_and_log test_upgrade->apm_callback_and_log ad_html_to_text ad_html_to_text (public) apm_callback_and_log->ad_html_to_text apm_dependency_check apm_dependency_check (private) apm_dependency_check->apm_callback_and_log apm_files_load apm_files_load (private) apm_files_load->apm_callback_and_log apm_load_apm_file apm_load_apm_file (public) apm_load_apm_file->apm_callback_and_log apm_package_deinstall apm_package_deinstall (public) apm_package_deinstall->apm_callback_and_log apm_package_delete apm_package_delete (public) apm_package_delete->apm_callback_and_log

Testcases:
upgrade

apm_callback_format_args (public)

 apm_callback_format_args [ -version_id version_id ] \
    [ -package_key package_key ] -type type [ -arg_list arg_list ]

Return a string on format -arg_name1 arg_value1 -arg_name2 arg_value2 ... for the callback proc of given type.

Switches:
-version_id (optional)
-package_key (optional)
-type (required)
-arg_list (optional)
Author:
Peter Marklund

Partial Call Graph (max 5 caller/called nodes):
%3 test_apm__test_callback_invoke apm__test_callback_invoke (test acs-tcl) apm_callback_format_args apm_callback_format_args test_apm__test_callback_invoke->apm_callback_format_args apm_arg_names_for_callback_type apm_arg_names_for_callback_type (public) apm_callback_format_args->apm_arg_names_for_callback_type apm_invoke_callback_proc apm_invoke_callback_proc (public) apm_invoke_callback_proc->apm_callback_format_args

Testcases:
apm__test_callback_invoke

apm_callback_has_valid_args (public)

 apm_callback_has_valid_args -type type -proc_name proc_name

Returns 1 if the specified callback proc of a certain type has a valid argument list in its definition and 0 otherwise. Assumes that the callback proc is defined with ad_proc.

Switches:
-type (required)
-proc_name (required)
Author:
Peter Marklund

Partial Call Graph (max 5 caller/called nodes):
%3 packages/acs-admin/www/apm/version-callback-add-edit.tcl packages/acs-admin/ www/apm/version-callback-add-edit.tcl apm_callback_has_valid_args apm_callback_has_valid_args packages/acs-admin/www/apm/version-callback-add-edit.tcl->apm_callback_has_valid_args apm_arg_names_for_callback_type apm_arg_names_for_callback_type (public) apm_callback_has_valid_args->apm_arg_names_for_callback_type nsf::cmd::info nsf::cmd::info apm_callback_has_valid_args->nsf::cmd::info

Testcases:
No testcase defined.

apm_callback_type_supported_p (public)

 apm_callback_type_supported_p type

Return 1 if the given type of callback is supported and 0 otherwise.

Parameters:
type (required)
Author:
Peter Marklund

Partial Call Graph (max 5 caller/called nodes):
%3 apm_assert_callback_type_supported apm_assert_callback_type_supported (public) apm_callback_type_supported_p apm_callback_type_supported_p apm_assert_callback_type_supported->apm_callback_type_supported_p apm_supported_callback_types apm_supported_callback_types (public) apm_callback_type_supported_p->apm_supported_callback_types

Testcases:
No testcase defined.

apm_dependency_add (public)

 apm_dependency_add [ -callback callback ] \
    [ -dependency_id dependency_id ] dependency_type version_id \
    dependency_uri dependency_version

Add a dependency to a version.

Switches:
-callback (optional, defaults to "apm_dummy_callback")
-dependency_id (optional)
Parameters:
dependency_type (required)
version_id (required)
dependency_uri (required)
dependency_version (required)
Returns:
The id of the new dependency.

Partial Call Graph (max 5 caller/called nodes):
%3 apm_package_install_dependencies apm_package_install_dependencies (private) apm_dependency_add apm_dependency_add apm_package_install_dependencies->apm_dependency_add packages/acs-admin/www/apm/version-dependency-add-2.tcl packages/acs-admin/ www/apm/version-dependency-add-2.tcl packages/acs-admin/www/apm/version-dependency-add-2.tcl->apm_dependency_add db_exec_plsql db_exec_plsql (public) apm_dependency_add->db_exec_plsql

Testcases:
No testcase defined.

apm_dependency_remove (public)

 apm_dependency_remove dependency_id

Removes a dependency from the system.

Parameters:
dependency_id (required)

Partial Call Graph (max 5 caller/called nodes):
%3 apm_package_install_dependencies apm_package_install_dependencies (private) apm_dependency_remove apm_dependency_remove apm_package_install_dependencies->apm_dependency_remove packages/acs-admin/www/apm/version-dependency-remove.tcl packages/acs-admin/ www/apm/version-dependency-remove.tcl packages/acs-admin/www/apm/version-dependency-remove.tcl->apm_dependency_remove db_exec_plsql db_exec_plsql (public) apm_dependency_remove->db_exec_plsql

Testcases:
No testcase defined.

apm_dummy_callback (public)

 apm_dummy_callback string

A dummy callback routine which does nothing.

Parameters:
string (required)

Partial Call Graph (max 5 caller/called nodes):
%3

Testcases:
No testcase defined.

apm_enabled_packages (public)

 apm_enabled_packages

Returns a list of package_key's for all enabled packages.

Author:
Peter Marklund

Partial Call Graph (max 5 caller/called nodes):
%3 api_add_calling_info_to_procdoc api_add_calling_info_to_procdoc (private) apm_enabled_packages apm_enabled_packages api_add_calling_info_to_procdoc->apm_enabled_packages apm_build_package_relationships apm_build_package_relationships (public) apm_build_package_relationships->apm_enabled_packages apm_load_libraries apm_load_libraries (private) apm_load_libraries->apm_enabled_packages apm_load_packages apm_load_packages (public) apm_load_packages->apm_enabled_packages apm_load_queries apm_load_queries (private) apm_load_queries->apm_enabled_packages db_list db_list (public) apm_enabled_packages->db_list

Testcases:
No testcase defined.

apm_flush_package_id_cache (public)

 apm_flush_package_id_cache package_key

Flush the package id cache for this package at least in the current thread. TODO: should be refactored together with the 2level cache (per thread and util_memoize).

Parameters:
package_key (required)

Partial Call Graph (max 5 caller/called nodes):
%3 packages/search/tcl/search-init.tcl packages/search/ tcl/search-init.tcl apm_flush_package_id_cache apm_flush_package_id_cache packages/search/tcl/search-init.tcl->apm_flush_package_id_cache search::init::schedule_indexer search::init::schedule_indexer (private) search::init::schedule_indexer->apm_flush_package_id_cache util_memoize_flush util_memoize_flush (public) apm_flush_package_id_cache->util_memoize_flush

Testcases:
No testcase defined.

apm_get_callback_proc (public)

 apm_get_callback_proc -type type [ -package_key package_key ] \
    [ -version_id version_id ]

Return Tcl procedure name for the callback of a certain type for the given package. If no callback proc for the given type is present returns the empty string.

Switches:
-type (required)
-package_key (optional)
-version_id (optional)
Author:
Peter Marklund
See Also:

Partial Call Graph (max 5 caller/called nodes):
%3 test_apm__test_callback_get_set apm__test_callback_get_set (test acs-tcl) apm_get_callback_proc apm_get_callback_proc test_apm__test_callback_get_set->apm_get_callback_proc apm_assert_callback_type_supported apm_assert_callback_type_supported (public) apm_get_callback_proc->apm_assert_callback_type_supported apm_version_id_from_package_key apm_version_id_from_package_key (public) apm_get_callback_proc->apm_version_id_from_package_key db_string db_string (public) apm_get_callback_proc->db_string apm_invoke_callback_proc apm_invoke_callback_proc (public) apm_invoke_callback_proc->apm_get_callback_proc apm_set_callback_proc apm_set_callback_proc (public) apm_set_callback_proc->apm_get_callback_proc packages/acs-admin/www/apm/version-callback-add-edit.tcl packages/acs-admin/ www/apm/version-callback-add-edit.tcl packages/acs-admin/www/apm/version-callback-add-edit.tcl->apm_get_callback_proc packages/acs-admin/www/apm/version-callback-invoke.tcl packages/acs-admin/ www/apm/version-callback-invoke.tcl packages/acs-admin/www/apm/version-callback-invoke.tcl->apm_get_callback_proc

Testcases:
apm__test_callback_get_set

apm_get_installed_provides (public)

 apm_get_installed_provides -array array

Sets the dependencies provided by the packages installed on this system in an array keyed by dependency service-uri.

Switches:
-array (required)
Name of array in caller's namespace where you want this set

Partial Call Graph (max 5 caller/called nodes):
%3 apm_dependency_check_new apm_dependency_check_new (public) apm_get_installed_provides apm_get_installed_provides apm_dependency_check_new->apm_get_installed_provides apm_get_installed_versions apm_get_installed_versions (public) apm_get_installed_provides->apm_get_installed_versions apm_version_names_compare apm_version_names_compare (public) apm_get_installed_provides->apm_version_names_compare db_foreach db_foreach (public) apm_get_installed_provides->db_foreach

Testcases:
No testcase defined.

apm_get_installed_versions (public)

 apm_get_installed_versions -array array

Sets the current installed version of packages installed on this system in an array keyed by package_key.

Switches:
-array (required)
Name of array in caller's namespace where you want this set

Partial Call Graph (max 5 caller/called nodes):
%3 test_files__check_xql_files files__check_xql_files (test acs-tcl) apm_get_installed_versions apm_get_installed_versions test_files__check_xql_files->apm_get_installed_versions test_files__page_contracts files__page_contracts (test acs-tcl) test_files__page_contracts->apm_get_installed_versions test_files__tcl_file_syntax_errors files__tcl_file_syntax_errors (test acs-tcl) test_files__tcl_file_syntax_errors->apm_get_installed_versions test_files__trailing_whitespace files__trailing_whitespace (test acs-tcl) test_files__trailing_whitespace->apm_get_installed_versions db_foreach db_foreach (public) apm_get_installed_versions->db_foreach apm_get_installed_provides apm_get_installed_provides (public) apm_get_installed_provides->apm_get_installed_versions apm_get_package_repository apm_get_package_repository (public) apm_get_package_repository->apm_get_installed_versions packages/acs-admin/www/apm/packages-install-2.tcl packages/acs-admin/ www/apm/packages-install-2.tcl packages/acs-admin/www/apm/packages-install-2.tcl->apm_get_installed_versions packages/acs-admin/www/install/install.tcl packages/acs-admin/ www/install/install.tcl packages/acs-admin/www/install/install.tcl->apm_get_installed_versions

Testcases:
files__tcl_file_syntax_errors, files__check_xql_files, files__trailing_whitespace, files__page_contracts

apm_highest_version (public)

 apm_highest_version package_key

Return the highest version of the indicated package.

Parameters:
package_key (required)
Returns:
the version_id of the highest installed version of a package.

Partial Call Graph (max 5 caller/called nodes):
%3 packages/acs-admin/www/apm/package-instances.tcl packages/acs-admin/ www/apm/package-instances.tcl apm_highest_version apm_highest_version packages/acs-admin/www/apm/package-instances.tcl->apm_highest_version packages/acs-admin/www/install/install-3.tcl packages/acs-admin/ www/install/install-3.tcl packages/acs-admin/www/install/install-3.tcl->apm_highest_version

Testcases:
No testcase defined.

apm_highest_version_name (public)

 apm_highest_version_name package_key

Return the highest version of the indicated package.

Parameters:
package_key (required)
Returns:
the version_name of the highest installed version of a package.

Partial Call Graph (max 5 caller/called nodes):
%3 apm_higher_version_installed_p apm_higher_version_installed_p (public) apm_highest_version_name apm_highest_version_name apm_higher_version_installed_p->apm_highest_version_name apm_package_upgrade_p apm_package_upgrade_p (public) apm_package_upgrade_p->apm_highest_version_name packages/acs-admin/www/install/install-3.tcl packages/acs-admin/ www/install/install-3.tcl packages/acs-admin/www/install/install-3.tcl->apm_highest_version_name xo::db::require proc function_args xo::db::require proc function_args (public) xo::db::require proc function_args->apm_highest_version_name db_string db_string (public) apm_highest_version_name->db_string

Testcases:
No testcase defined.

apm_instance_name_from_id (public)

 apm_instance_name_from_id package_id
Parameters:
package_id (required)
Returns:
The name of the instance.

Partial Call Graph (max 5 caller/called nodes):
%3 fs::install::after_instantiate fs::install::after_instantiate (private) apm_instance_name_from_id apm_instance_name_from_id fs::install::after_instantiate->apm_instance_name_from_id fs::new_root_folder fs::new_root_folder (public) fs::new_root_folder->apm_instance_name_from_id packages/acs-lang/www/change-locale-include.tcl packages/acs-lang/ www/change-locale-include.tcl packages/acs-lang/www/change-locale-include.tcl->apm_instance_name_from_id packages/acs-subsite/www/admin/applications/application-delete.tcl packages/acs-subsite/ www/admin/applications/application-delete.tcl packages/acs-subsite/www/admin/applications/application-delete.tcl->apm_instance_name_from_id packages/acs-subsite/www/admin/applications/permissions-user-add.tcl packages/acs-subsite/ www/admin/applications/permissions-user-add.tcl packages/acs-subsite/www/admin/applications/permissions-user-add.tcl->apm_instance_name_from_id apm_instance_name_from_id_not_cached apm_instance_name_from_id_not_cached (private) apm_instance_name_from_id->apm_instance_name_from_id_not_cached util_memoize util_memoize (public) apm_instance_name_from_id->util_memoize

Testcases:
No testcase defined.

apm_interface_add (public)

 apm_interface_add [ -callback callback ] \
    [ -interface_id interface_id ] version_id interface_uri \
    interface_version

Add a interface to a version.

Switches:
-callback (optional, defaults to "apm_dummy_callback")
-interface_id (optional)
Parameters:
version_id (required)
interface_uri (required)
interface_version (required)
Returns:
The id of the new interface.

Partial Call Graph (max 5 caller/called nodes):
%3 test_upgrade upgrade (test acs-lang) apm_interface_add apm_interface_add test_upgrade->apm_interface_add db_exec_plsql db_exec_plsql (public) apm_interface_add->db_exec_plsql apm_package_install_dependencies apm_package_install_dependencies (private) apm_package_install_dependencies->apm_interface_add apm_package_install_version apm_package_install_version (public) apm_package_install_version->apm_interface_add

Testcases:
upgrade

apm_interface_remove (public)

 apm_interface_remove interface_id

Removes a interface from the system.

Parameters:
interface_id (required)

Partial Call Graph (max 5 caller/called nodes):
%3 db_exec_plsql db_exec_plsql (public) apm_interface_remove apm_interface_remove apm_interface_remove->db_exec_plsql

Testcases:
No testcase defined.

apm_invoke_callback_proc (public)

 apm_invoke_callback_proc [ -proc_name proc_name ] \
    [ -version_id version_id ] [ -package_key package_key ] \
    [ -arg_list arg_list ] -type type

Invoke the Tcl callback proc of a given type for a given package version. Any errors during invocation are logged.

Switches:
-proc_name (optional)
if this is provided it is called instead of attempting to look up the proc via the package_key or version_id (needed for before-install callbacks since the db is not populated when those are called).
-version_id (optional)
-package_key (optional)
-arg_list (optional)
-type (required)
Returns:
1 if invocation was carried out successfully, 0 if no proc to invoke could be found. Will propagate any error thrown by the callback.
Author:
Peter Marklund

Partial Call Graph (max 5 caller/called nodes):
%3 test_apm__test_callback_invoke apm__test_callback_invoke (test acs-tcl) apm_invoke_callback_proc apm_invoke_callback_proc test_apm__test_callback_invoke->apm_invoke_callback_proc apm_callback_format_args apm_callback_format_args (public) apm_invoke_callback_proc->apm_callback_format_args apm_get_callback_proc apm_get_callback_proc (public) apm_invoke_callback_proc->apm_get_callback_proc apm_package_key_from_version_id apm_package_key_from_version_id (public) apm_invoke_callback_proc->apm_package_key_from_version_id apm_post_instantiation_tcl_proc_from_key apm_post_instantiation_tcl_proc_from_key (private) apm_invoke_callback_proc->apm_post_instantiation_tcl_proc_from_key apm::convert_type apm::convert_type (public) apm::convert_type->apm_invoke_callback_proc apm_package_delete apm_package_delete (public) apm_package_delete->apm_invoke_callback_proc apm_package_install apm_package_install (public) apm_package_install->apm_invoke_callback_proc apm_package_instance_delete apm_package_instance_delete (public) apm_package_instance_delete->apm_invoke_callback_proc apm_package_instance_new apm_package_instance_new (public) apm_package_instance_new->apm_invoke_callback_proc

Testcases:
apm__test_callback_invoke

apm_load_any_changed_libraries (public)

 apm_load_any_changed_libraries [ -version_files version_files ] \
    [ errorVarName ]

In the running interpreter, reloads files marked for reload by apm_mark_version_for_reload. If any watches are set, examines watched files to see whether they need to be reloaded as well. This is intended to be called only by the request processor (since it should be invoked before any filters or registered procedures are applied).

Switches:
-version_files (optional)
Parameters:
errorVarName (optional)

Partial Call Graph (max 5 caller/called nodes):
%3 packages/acs-admin/www/apm/version-reload.tcl packages/acs-admin/ www/apm/version-reload.tcl apm_load_any_changed_libraries apm_load_any_changed_libraries packages/acs-admin/www/apm/version-reload.tcl->apm_load_any_changed_libraries rp_filter rp_filter (private) rp_filter->apm_load_any_changed_libraries apm_get_changed_watched_files apm_get_changed_watched_files (private) apm_load_any_changed_libraries->apm_get_changed_watched_files apm_package_reload_cmds apm_package_reload_cmds (private) apm_load_any_changed_libraries->apm_package_reload_cmds

Testcases:
No testcase defined.

apm_load_packages (public)

 apm_load_packages [ -force_reload ] \
    [ -load_libraries_p load_libraries_p ] \
    [ -load_queries_p load_queries_p ] [ -packages packages ]

Load Tcl libraries and queries for the packages with given keys into the current interpreter. Will load Tcl tests when the acs-automated-testing package is enabled.

Switches:
-force_reload (optional, boolean, defaults to "0")
Reload Tcl libraries even if they are already loaded.
-load_libraries_p (optional, defaults to "1")
Switch to indicate if Tcl libraries in (-procs.tcl and -init.tcl) files should be loaded. Defaults to true.
-load_queries_p (optional, defaults to "1")
Switch to indicate if xql query files should be loaded. Default true.
-packages (optional)
A list of package_keys for packages to be loaded. Defaults to all enabled packages. These packages, along with the packages they depend on, will be loaded in dependency-order using the information provided via the "provides" and "requires" definitions.
Author:
Peter Marklund
See Also:

Partial Call Graph (max 5 caller/called nodes):
%3 packages/acs-bootstrap-installer/bootstrap.tcl packages/acs-bootstrap-installer/ bootstrap.tcl apm_load_packages apm_load_packages packages/acs-bootstrap-installer/bootstrap.tcl->apm_load_packages apm_enabled_packages apm_enabled_packages (public) apm_load_packages->apm_enabled_packages apm_load_libraries apm_load_libraries (private) apm_load_packages->apm_load_libraries apm_load_queries apm_load_queries (private) apm_load_packages->apm_load_queries apm_load_tests_p apm_load_tests_p (public) apm_load_packages->apm_load_tests_p apm_package_load_libraries_order apm_package_load_libraries_order (public) apm_load_packages->apm_package_load_libraries_order

Testcases:
No testcase defined.

apm_load_tests_p (public)

 apm_load_tests_p

Determine whether to load acs-automated-testing tests for packages.

Returns:
1 if tests should be loaded and 0 otherwise
Author:
Peter Marklund

Partial Call Graph (max 5 caller/called nodes):
%3 apm_load_packages apm_load_packages (public) apm_load_tests_p apm_load_tests_p apm_load_packages->apm_load_tests_p apm_mark_version_for_reload apm_mark_version_for_reload (public) apm_mark_version_for_reload->apm_load_tests_p apm_version_load_status apm_version_load_status (public) apm_version_load_status->apm_load_tests_p packages/acs-bootstrap-installer/bootstrap.tcl packages/acs-bootstrap-installer/ bootstrap.tcl packages/acs-bootstrap-installer/bootstrap.tcl->apm_load_tests_p apm_package_enabled_p apm_package_enabled_p (public) apm_load_tests_p->apm_package_enabled_p

Testcases:
No testcase defined.

apm_log (public)

 apm_log level msg

Centralized APM logging. If you want to debug the APM, change APMDebug to Debug and restart the server.

Parameters:
level (required)
msg (required)

Partial Call Graph (max 5 caller/called nodes):
%3 apm_data_model_scripts_find apm_data_model_scripts_find (public) apm_log apm_log apm_data_model_scripts_find->apm_log apm_generate_package_spec apm_generate_package_spec (public) apm_generate_package_spec->apm_log apm_read_package_info_file apm_read_package_info_file (public) apm_read_package_info_file->apm_log packages/acs-admin/www/apm/packages-install.tcl packages/acs-admin/ www/apm/packages-install.tcl packages/acs-admin/www/apm/packages-install.tcl->apm_log

Testcases:
No testcase defined.

apm_mark_files_for_reload (public)

 apm_mark_files_for_reload [ -force_reload ] file_list

Mark the given list of Tcl and query files for reload in all interpreters. Only marks files for reload if they haven't been loaded before or they have changed since last reload.

Switches:
-force_reload (optional, boolean)
Mark the files for reload even if their modification time in the nsv cache doesn't differ from the one in the filesystem.
Parameters:
file_list (required)
A list of paths relative to $::acs::rootdir
Returns:
The list of files marked for reload.
Author:
Peter Marklund

Partial Call Graph (max 5 caller/called nodes):
%3 test_acs_sc_impl_new_from_spec acs_sc_impl_new_from_spec (test acs-service-contract) apm_mark_files_for_reload apm_mark_files_for_reload test_acs_sc_impl_new_from_spec->apm_mark_files_for_reload ad_file ad_file (public) apm_mark_files_for_reload->ad_file acs_sc::impl::binding::init_procs acs_sc::impl::binding::init_procs (private) acs_sc::impl::binding::init_procs->apm_mark_files_for_reload apm_mark_version_for_reload apm_mark_version_for_reload (public) apm_mark_version_for_reload->apm_mark_files_for_reload

Testcases:
acs_sc_impl_new_from_spec

apm_mark_version_for_reload (public)

 apm_mark_version_for_reload version_id [ changed_files_var ]

Examines all tcl_procs files in package version $version_id; if any have changed since they were loaded, marks (in the apm_reload array) that they must be reloaded by each Tcl interpreter (using the apm_load_any_changed_libraries procedure).

Saves a list of files that have changed (and thus marked to be reloaded) in the variable named $file_info_var, if provided. Each element of this list is of the form:

[list $file_id $path]

Parameters:
version_id (required)
changed_files_var (optional)

Partial Call Graph (max 5 caller/called nodes):
%3 packages/acs-admin/www/apm/version-reload.tcl packages/acs-admin/ www/apm/version-reload.tcl apm_mark_version_for_reload apm_mark_version_for_reload packages/acs-admin/www/apm/version-reload.tcl->apm_mark_version_for_reload packages/acs-automated-testing/www/admin/record-test.tcl packages/acs-automated-testing/ www/admin/record-test.tcl packages/acs-automated-testing/www/admin/record-test.tcl->apm_mark_version_for_reload acs_package_root_dir acs_package_root_dir (public) apm_mark_version_for_reload->acs_package_root_dir apm_get_package_files apm_get_package_files (public) apm_mark_version_for_reload->apm_get_package_files apm_load_tests_p apm_load_tests_p (public) apm_mark_version_for_reload->apm_load_tests_p apm_mark_files_for_reload apm_mark_files_for_reload (public) apm_mark_version_for_reload->apm_mark_files_for_reload apm_package_key_from_version_id apm_package_key_from_version_id (public) apm_mark_version_for_reload->apm_package_key_from_version_id

Testcases:
No testcase defined.

apm_ns_write_callback (public)

 apm_ns_write_callback string

A simple callback which prints out the log message to the server stream.

Parameters:
string (required)

Partial Call Graph (max 5 caller/called nodes):
%3

Testcases:
No testcase defined.

apm_num_instances (public)

 apm_num_instances package_key
Parameters:
package_key (required)
Returns:
The number of instances of the indicated package.

Partial Call Graph (max 5 caller/called nodes):
%3 packages/acs-admin/www/apm/version-view.tcl packages/acs-admin/ www/apm/version-view.tcl apm_num_instances apm_num_instances packages/acs-admin/www/apm/version-view.tcl->apm_num_instances db_string db_string (public) apm_num_instances->db_string

Testcases:
No testcase defined.

apm_one_package_inherit_order (public)

 apm_one_package_inherit_order package_key

Returns a list of package keys in package inheritance order.

Parameters:
package_key (required)

Partial Call Graph (max 5 caller/called nodes):
%3 apm_build_one_package_relationships apm_build_one_package_relationships (public) apm_one_package_inherit_order apm_one_package_inherit_order apm_build_one_package_relationships->apm_one_package_inherit_order apm_generate_package_spec apm_generate_package_spec (public) apm_generate_package_spec->apm_one_package_inherit_order packages/acs-admin/www/apm/version-parameters.tcl packages/acs-admin/ www/apm/version-parameters.tcl packages/acs-admin/www/apm/version-parameters.tcl->apm_one_package_inherit_order db_list db_list (public) apm_one_package_inherit_order->db_list

Testcases:
No testcase defined.

apm_package_descendents (public)

 apm_package_descendents package_key

Wrapper that returns the cached package descendents list.

Parameters:
package_key (required)

Partial Call Graph (max 5 caller/called nodes):
%3 apm::get_package_descendent_options apm::get_package_descendent_options (public) apm_package_descendents apm_package_descendents apm::get_package_descendent_options->apm_package_descendents

Testcases:
No testcase defined.

apm_package_enabled_p (public)

 apm_package_enabled_p package_key

Returns 1 if there is an enabled package version corresponding to the package_key and 0 otherwise.

Parameters:
package_key (required)

Partial Call Graph (max 5 caller/called nodes):
%3 Object ::template::CSS Object ::template::CSS (public) apm_package_enabled_p apm_package_enabled_p Object ::template::CSS->apm_package_enabled_p apm_data_model_scripts_find apm_data_model_scripts_find (public) apm_data_model_scripts_find->apm_package_enabled_p apm_load_tests_p apm_load_tests_p (public) apm_load_tests_p->apm_package_enabled_p ds_watch_packages ds_watch_packages (private) ds_watch_packages->apm_package_enabled_p packages/acs-admin/www/install/install-3.tcl packages/acs-admin/ www/install/install-3.tcl packages/acs-admin/www/install/install-3.tcl->apm_package_enabled_p acs::try_cache acs::try_cache (private) apm_package_enabled_p->acs::try_cache db_0or1row db_0or1row (public) apm_package_enabled_p->db_0or1row

Testcases:
No testcase defined.

apm_package_id_from_key (public)

 apm_package_id_from_key package_key
Parameters:
package_key (required)
Returns:
The package id of the instance of the package. 0 if no instance exists, error if several instances exist.

Partial Call Graph (max 5 caller/called nodes):
%3 test_acs_mail_lite_inbound_procs_check acs_mail_lite_inbound_procs_check (test acs-mail-lite) apm_package_id_from_key apm_package_id_from_key test_acs_mail_lite_inbound_procs_check->apm_package_id_from_key test_acs_object_procs_test acs_object_procs_test (test acs-tcl) test_acs_object_procs_test->apm_package_id_from_key test_locale__test_system_package_setting locale__test_system_package_setting (test acs-lang) test_locale__test_system_package_setting->apm_package_id_from_key test_logout_from_everywhere logout_from_everywhere (test acs-tcl) test_logout_from_everywhere->apm_package_id_from_key test_parameter__check_procs parameter__check_procs (test acs-tcl) test_parameter__check_procs->apm_package_id_from_key apm_package_id_from_key_not_cached apm_package_id_from_key_not_cached (private) apm_package_id_from_key->apm_package_id_from_key_not_cached util_memoize util_memoize (public) apm_package_id_from_key->util_memoize acs::test::url acs::test::url (public) acs::test::url->apm_package_id_from_key acs_mail_lite::bounce_address acs_mail_lite::bounce_address (private) acs_mail_lite::bounce_address->apm_package_id_from_key acs_mail_lite::check_bounces acs_mail_lite::check_bounces (private) acs_mail_lite::check_bounces->apm_package_id_from_key acs_mail_lite::get_package_id acs_mail_lite::get_package_id (private) acs_mail_lite::get_package_id->apm_package_id_from_key acs_mail_lite::imap_check_incoming acs_mail_lite::imap_check_incoming (private) acs_mail_lite::imap_check_incoming->apm_package_id_from_key

Testcases:
locale__test_system_package_setting, acs_mail_lite_inbound_procs_check, parameter_register_test, parameter__check_procs, acs_object_procs_test, logout_from_everywhere

apm_package_ids_from_key (public)

 apm_package_ids_from_key -package_key package_key [ -mounted ]
Switches:
-package_key (required)
The package key we are looking for the package
-mounted (optional, boolean)
Does the package have to be mounted?
Returns:
List of package ids of all instances of the package. Empty string

Partial Call Graph (max 5 caller/called nodes):
%3 cookieconsent::after-upgrade cookieconsent::after-upgrade (private) apm_package_ids_from_key apm_package_ids_from_key cookieconsent::after-upgrade->apm_package_ids_from_key email_image::get_priv_email email_image::get_priv_email (public) email_image::get_priv_email->apm_package_ids_from_key email_image::get_priv_email_from_parameter email_image::get_priv_email_from_parameter (private) email_image::get_priv_email_from_parameter->apm_package_ids_from_key forum::use_ReadingInfo_p forum::use_ReadingInfo_p (public) forum::use_ReadingInfo_p->apm_package_ids_from_key install::xml::object_id::package install::xml::object_id::package (public) install::xml::object_id::package->apm_package_ids_from_key apm_package_ids_from_key_not_cached apm_package_ids_from_key_not_cached (private) apm_package_ids_from_key->apm_package_ids_from_key_not_cached util_memoize util_memoize (public) apm_package_ids_from_key->util_memoize

Testcases:
No testcase defined.

apm_package_inherit_order (public)

 apm_package_inherit_order package_key

Wrapper that returns the cached package inheritance order list.

Parameters:
package_key (required)

Partial Call Graph (max 5 caller/called nodes):
%3 apm::convert_type apm::convert_type (public) apm_package_inherit_order apm_package_inherit_order apm::convert_type->apm_package_inherit_order

Testcases:
No testcase defined.

apm_package_installed_p (public)

 apm_package_installed_p package_key

Returns 1 if there is an installed package version corresponding to the package_key, 0 otherwise. Uses a cached value for performance.

Parameters:
package_key (required)

Partial Call Graph (max 5 caller/called nodes):
%3 test_files__check_info_files files__check_info_files (test acs-tcl) apm_package_installed_p apm_package_installed_p test_files__check_info_files->apm_package_installed_p acs::try_cache acs::try_cache (private) apm_package_installed_p->acs::try_cache db_0or1row db_0or1row (public) apm_package_installed_p->db_0or1row Class ::xo::Authorize Class ::xo::Authorize (public) Class ::xo::Authorize->apm_package_installed_p ad_verify_install ad_verify_install (public) ad_verify_install->apm_package_installed_p apm_data_model_scripts_find apm_data_model_scripts_find (public) apm_data_model_scripts_find->apm_package_installed_p apm_load_catalog_files apm_load_catalog_files (private) apm_load_catalog_files->apm_package_installed_p apm_scan_packages apm_scan_packages (public) apm_scan_packages->apm_package_installed_p

Testcases:
files__check_info_files

apm_package_instance_delete (public)

 apm_package_instance_delete package_id

Deletes an instance of a package

Parameters:
package_id (required)

Partial Call Graph (max 5 caller/called nodes):
%3 apm_package_delete apm_package_delete (public) apm_package_instance_delete apm_package_instance_delete apm_package_delete->apm_package_instance_delete packages/acs-subsite/www/admin/applications/application-delete.tcl packages/acs-subsite/ www/admin/applications/application-delete.tcl packages/acs-subsite/www/admin/applications/application-delete.tcl->apm_package_instance_delete packages/acs-subsite/www/admin/site-map/instance-delete.tcl packages/acs-subsite/ www/admin/site-map/instance-delete.tcl packages/acs-subsite/www/admin/site-map/instance-delete.tcl->apm_package_instance_delete site_node::delete site_node::delete (public) site_node::delete->apm_package_instance_delete site_node_apm_integration::delete_site_nodes_and_package site_node_apm_integration::delete_site_nodes_and_package (public) site_node_apm_integration::delete_site_nodes_and_package->apm_package_instance_delete apm_invoke_callback_proc apm_invoke_callback_proc (public) apm_package_instance_delete->apm_invoke_callback_proc apm_package_key_from_id apm_package_key_from_id (public) apm_package_instance_delete->apm_package_key_from_id db_exec_plsql db_exec_plsql (public) apm_package_instance_delete->db_exec_plsql

Testcases:
No testcase defined.

apm_package_instance_new (public)

 apm_package_instance_new -package_key package_key \
    [ -instance_name instance_name ] [ -package_id package_id ] \
    [ -context_id context_id ]

Creates a new instance of a package and calls the post instantiation proc, if any. If the package is a singleton and already exists then this procedure will silently do nothing.

Switches:
-package_key (required)
The package_key of the package to instantiate.
-instance_name (optional)
The name of the package instance, defaults to the pretty name of the package type.
-package_id (optional)
The id of the new package. Optional.
-context_id (optional)
The context_id of the new package. Optional.
Returns:
The id of the instantiated package

Partial Call Graph (max 5 caller/called nodes):
%3 test_test_apm_package_instance__new test_apm_package_instance__new (test acs-tcl) apm_package_instance_new apm_package_instance_new test_test_apm_package_instance__new->apm_package_instance_new apm::package_version::attributes::get_instance_name apm::package_version::attributes::get_instance_name (private) apm_package_instance_new->apm::package_version::attributes::get_instance_name apm_invoke_callback_proc apm_invoke_callback_proc (public) apm_package_instance_new->apm_invoke_callback_proc apm_parameter_sync apm_parameter_sync (public) apm_package_instance_new->apm_parameter_sync db_0or1row db_0or1row (public) apm_package_instance_new->db_0or1row db_exec_plsql db_exec_plsql (public) apm_package_instance_new->db_exec_plsql apm_package_install apm_package_install (public) apm_package_install->apm_package_instance_new install::xml::action::create-package install::xml::action::create-package (public) install::xml::action::create-package->apm_package_instance_new packages/acs-admin/www/apm/package-instance-create.tcl packages/acs-admin/ www/apm/package-instance-create.tcl packages/acs-admin/www/apm/package-instance-create.tcl->apm_package_instance_new site_node::instantiate_and_mount site_node::instantiate_and_mount (public) site_node::instantiate_and_mount->apm_package_instance_new

Testcases:
test_apm_package_instance__new

apm_package_key_from_id (public)

 apm_package_key_from_id package_id
Parameters:
package_id (required)
Returns:
The package key of the instance.

Partial Call Graph (max 5 caller/called nodes):
%3 acs::test::require_package_instance acs::test::require_package_instance (public) apm_package_key_from_id apm_package_key_from_id acs::test::require_package_instance->apm_package_key_from_id apm_package_instance_delete apm_package_instance_delete (public) apm_package_instance_delete->apm_package_key_from_id callback::subsite::parameter_changed::impl::acs-content-repository callback::subsite::parameter_changed::impl::acs-content-repository (private) callback::subsite::parameter_changed::impl::acs-content-repository->apm_package_key_from_id callback::subsite::parameter_changed::impl::xotcl-core_param_changed callback::subsite::parameter_changed::impl::xotcl-core_param_changed (private) callback::subsite::parameter_changed::impl::xotcl-core_param_changed->apm_package_key_from_id fs::new_folder fs::new_folder (public) fs::new_folder->apm_package_key_from_id db_string db_string (public) apm_package_key_from_id->db_string

Testcases:
No testcase defined.

apm_package_key_from_version_id (public)

 apm_package_key_from_version_id version_id

Returns the package_key for the given APM package version id. Goes to the database the first time called and then uses a cached value. Calls the proc apm_package_key_from_version_id_mem.

Parameters:
version_id (required)
Author:
Peter Marklund <peter@collaboraid.biz>

Partial Call Graph (max 5 caller/called nodes):
%3 apm_generate_tarball apm_generate_tarball (public) apm_package_key_from_version_id apm_package_key_from_version_id apm_generate_tarball->apm_package_key_from_version_id apm_invoke_callback_proc apm_invoke_callback_proc (public) apm_invoke_callback_proc->apm_package_key_from_version_id apm_mark_version_for_reload apm_mark_version_for_reload (public) apm_mark_version_for_reload->apm_package_key_from_version_id apm_version_disable apm_version_disable (public) apm_version_disable->apm_package_key_from_version_id apm_version_enable apm_version_enable (public) apm_version_enable->apm_package_key_from_version_id apm_package_key_from_version_id_not_cached apm_package_key_from_version_id_not_cached (private) apm_package_key_from_version_id->apm_package_key_from_version_id_not_cached util_memoize util_memoize (public) apm_package_key_from_version_id->util_memoize

Testcases:
No testcase defined.

apm_package_list_url_resolution (public)

 apm_package_list_url_resolution package_list

Use a left-right, breadth-first traverse of the inheritance DAG to build a structure to be used by the request processor to resolve URLs based on a package's "extends" and "embeds" dependencies.

Parameters:
package_list (required)

Partial Call Graph (max 5 caller/called nodes):
%3 apm_build_one_package_relationships apm_build_one_package_relationships (public) apm_package_list_url_resolution apm_package_list_url_resolution apm_build_one_package_relationships->apm_package_list_url_resolution db_1row db_1row (public) apm_package_list_url_resolution->db_1row db_list_of_lists db_list_of_lists (public) apm_package_list_url_resolution->db_list_of_lists

Testcases:
No testcase defined.

apm_package_load_libraries_order (public)

 apm_package_load_libraries_order package_key

Wrapper that returns the cached package library load order list.

Parameters:
package_key (required)

Partial Call Graph (max 5 caller/called nodes):
%3 test_apm_dependencies_api apm_dependencies_api (test acs-tcl) apm_package_load_libraries_order apm_package_load_libraries_order test_apm_dependencies_api->apm_package_load_libraries_order apm_load_packages apm_load_packages (public) apm_load_packages->apm_package_load_libraries_order

Testcases:
apm_dependencies_api

apm_package_parameters (public)

 apm_package_parameters package_key
Parameters:
package_key (required)
Returns:
A list of all the package parameter names.

Partial Call Graph (max 5 caller/called nodes):
%3 db_list db_list (public) apm_package_parameters apm_package_parameters apm_package_parameters->db_list

Testcases:
No testcase defined.

apm_package_registered_p (public)

 apm_package_registered_p package_key

Returns 1 if there is a registered package with the indicated package_key. Returns 0 otherwise.

Parameters:
package_key (required)

Partial Call Graph (max 5 caller/called nodes):
%3 ad_core_docs_uninstalled_packages_internal ad_core_docs_uninstalled_packages_internal (private) apm_package_registered_p apm_package_registered_p ad_core_docs_uninstalled_packages_internal->apm_package_registered_p apm_package_deinstall apm_package_deinstall (public) apm_package_deinstall->apm_package_registered_p apm_package_install apm_package_install (public) apm_package_install->apm_package_registered_p apm_package_selection_widget apm_package_selection_widget (private) apm_package_selection_widget->apm_package_registered_p packages/acs-admin/www/apm/package-add-2.tcl packages/acs-admin/ www/apm/package-add-2.tcl packages/acs-admin/www/apm/package-add-2.tcl->apm_package_registered_p db_0or1row db_0or1row (public) apm_package_registered_p->db_0or1row

Testcases:
No testcase defined.

apm_package_rename (public)

 apm_package_rename [ -package_id package_id ] \
    -instance_name instance_name

Renames a package instance

Switches:
-package_id (optional)
-instance_name (required)

Partial Call Graph (max 5 caller/called nodes):
%3 install::xml::action::rename-instance install::xml::action::rename-instance (public) apm_package_rename apm_package_rename install::xml::action::rename-instance->apm_package_rename packages/acs-subsite/www/admin/applications/application-add.tcl packages/acs-subsite/ www/admin/applications/application-add.tcl packages/acs-subsite/www/admin/applications/application-add.tcl->apm_package_rename packages/acs-subsite/www/admin/configure.tcl packages/acs-subsite/ www/admin/configure.tcl packages/acs-subsite/www/admin/configure.tcl->apm_package_rename packages/acs-subsite/www/admin/site-map/rename.tcl packages/acs-subsite/ www/admin/site-map/rename.tcl packages/acs-subsite/www/admin/site-map/rename.tcl->apm_package_rename ad_conn ad_conn (public) apm_package_rename->ad_conn db_dml db_dml (public) apm_package_rename->db_dml db_list db_list (public) apm_package_rename->db_list db_transaction db_transaction (public) apm_package_rename->db_transaction site_node::update_cache site_node::update_cache (public) apm_package_rename->site_node::update_cache

Testcases:
No testcase defined.

apm_package_supported_databases (public)

 apm_package_supported_databases package_key

Return a list of db types (i.e. oracle, postgresql) supported by the package with given key.

Parameters:
package_key (required)
Author:
Peter Marklund
See Also:

Partial Call Graph (max 5 caller/called nodes):
%3 packages/acs-admin/www/apm/version-view.tcl packages/acs-admin/ www/apm/version-view.tcl apm_package_supported_databases apm_package_supported_databases packages/acs-admin/www/apm/version-view.tcl->apm_package_supported_databases apm_package_supports_rdbms_p apm_package_supports_rdbms_p (public) apm_package_supported_databases->apm_package_supports_rdbms_p db_known_database_types db_known_database_types (public) apm_package_supported_databases->db_known_database_types

Testcases:
No testcase defined.

apm_package_url_from_id (public)

 apm_package_url_from_id package_id

Will return the first url found for a given package_id

Parameters:
package_id (required)
Returns:
The package url of the instance of the package.

Partial Call Graph (max 5 caller/called nodes):
%3 apm_package_url_from_key apm_package_url_from_key (public) apm_package_url_from_id apm_package_url_from_id apm_package_url_from_key->apm_package_url_from_id bug_tracker::bug::notification_info::get_notification_info bug_tracker::bug::notification_info::get_notification_info (private) bug_tracker::bug::notification_info::get_notification_info->apm_package_url_from_id bug_tracker::search::bug::datasource bug_tracker::search::bug::datasource (private) bug_tracker::search::bug::datasource->apm_package_url_from_id bug_tracker::search::bug::url bug_tracker::search::bug::url (private) bug_tracker::search::bug::url->apm_package_url_from_id bug_tracker::search::patch::url bug_tracker::search::patch::url (private) bug_tracker::search::patch::url->apm_package_url_from_id site_node::get_url_from_object_id site_node::get_url_from_object_id (public) apm_package_url_from_id->site_node::get_url_from_object_id

Testcases:
No testcase defined.

apm_package_url_from_key (public)

 apm_package_url_from_key package_key
Parameters:
package_key (required)
Returns:
The package url of the instance of the package. only valid for singleton packages.

Partial Call Graph (max 5 caller/called nodes):
%3 adp_parse_ad_conn_file adp_parse_ad_conn_file (private) apm_package_url_from_key apm_package_url_from_key adp_parse_ad_conn_file->apm_package_url_from_key ds_support_url ds_support_url (private) ds_support_url->apm_package_url_from_key lang::util::edit_lang_key_url lang::util::edit_lang_key_url (public) lang::util::edit_lang_key_url->apm_package_url_from_key notification::display::get_urls notification::display::get_urls (public) notification::display::get_urls->apm_package_url_from_key notification::display::request_widget notification::display::request_widget (public) notification::display::request_widget->apm_package_url_from_key apm_package_id_from_key apm_package_id_from_key (public) apm_package_url_from_key->apm_package_id_from_key apm_package_url_from_id apm_package_url_from_id (public) apm_package_url_from_key->apm_package_url_from_id

Testcases:
No testcase defined.

apm_package_url_resolution (public)

 apm_package_url_resolution package_key

Wrapper that returns the cached package search order list.

Parameters:
package_key (required)

Partial Call Graph (max 5 caller/called nodes):
%3 rp_handle_request rp_handle_request (private) apm_package_url_resolution apm_package_url_resolution rp_handle_request->apm_package_url_resolution

Testcases:
No testcase defined.

apm_package_version_enabled_p (public)

 apm_package_version_enabled_p version_id
Parameters:
version_id (required)
Returns:
1 if the indicated package version is installed, 0 otherwise.

Partial Call Graph (max 5 caller/called nodes):
%3 apm_version_load_status apm_version_load_status (public) apm_package_version_enabled_p apm_package_version_enabled_p apm_version_load_status->apm_package_version_enabled_p db_string db_string (public) apm_package_version_enabled_p->db_string

Testcases:
No testcase defined.

apm_package_version_installed_p (public)

 apm_package_version_installed_p package_key version_name
Parameters:
package_key (required)
version_name (required)
Returns:
1 if the indicated package version is installed, 0 otherwise.

Partial Call Graph (max 5 caller/called nodes):
%3 apm_load_apm_file apm_load_apm_file (public) apm_package_version_installed_p apm_package_version_installed_p apm_load_apm_file->apm_package_version_installed_p packages/acs-admin/www/apm/packages-install-4.tcl packages/acs-admin/ www/apm/packages-install-4.tcl packages/acs-admin/www/apm/packages-install-4.tcl->apm_package_version_installed_p packages/acs-admin/www/install/install-3.tcl packages/acs-admin/ www/install/install-3.tcl packages/acs-admin/www/install/install-3.tcl->apm_package_version_installed_p db_0or1row db_0or1row (public) apm_package_version_installed_p->db_0or1row

Testcases:
No testcase defined.

apm_parameter_register (public)

 apm_parameter_register [ -callback callback ] \
    [ -parameter_id parameter_id ] [ -scope scope ] parameter_name \
    description package_key default_value datatype [ section_name ] \
    [ min_n_values ] [ max_n_values ]

Register a parameter in the system. The new "scope" parameter is named rather than positional to avoid breaking existing code.

Switches:
-callback (optional, defaults to "apm_dummy_callback")
-parameter_id (optional)
-scope (optional, defaults to "instance")
Parameters:
parameter_name (required)
description (required)
package_key (required)
default_value (required)
datatype (required)
section_name (optional)
min_n_values (optional, defaults to "1")
max_n_values (optional, defaults to "1")
Returns:
The parameter id of the new parameter.

Partial Call Graph (max 5 caller/called nodes):
%3 test_parameter__check_procs parameter__check_procs (test acs-tcl) apm_parameter_register apm_parameter_register test_parameter__check_procs->apm_parameter_register test_parameter_register_test parameter_register_test (test acs-tcl) test_parameter_register_test->apm_parameter_register test_test_apm_parameter__register test_apm_parameter__register (test acs-tcl) test_test_apm_parameter__register->apm_parameter_register apm_copy_param_to_descendents apm_copy_param_to_descendents (public) apm_parameter_register->apm_copy_param_to_descendents db_exec_plsql db_exec_plsql (public) apm_parameter_register->db_exec_plsql acs_admin::check_expired_certificates acs_admin::check_expired_certificates (private) acs_admin::check_expired_certificates->apm_parameter_register apm_package_install_parameters apm_package_install_parameters (private) apm_package_install_parameters->apm_parameter_register apm_package_upgrade_parameters apm_package_upgrade_parameters (private) apm_package_upgrade_parameters->apm_parameter_register boomerang::after-install boomerang::after-install (private) boomerang::after-install->apm_parameter_register cookieconsent::after-install cookieconsent::after-install (private) cookieconsent::after-install->apm_parameter_register

Testcases:
test_apm_parameter__register, parameter_register_test, parameter__check_procs

apm_parameter_sync (public)

 apm_parameter_sync package_key package_id

Syncs the parameters in the database with the memory cache. This must be called after creating a new package instance.

Parameters:
package_key (required)
package_id (required)

Partial Call Graph (max 5 caller/called nodes):
%3 apm::convert_type apm::convert_type (public) apm_parameter_sync apm_parameter_sync apm::convert_type->apm_parameter_sync apm_package_instance_new apm_package_instance_new (public) apm_package_instance_new->apm_parameter_sync packages/edit-this-page/www/etp-setup.tcl packages/edit-this-page/ www/etp-setup.tcl packages/edit-this-page/www/etp-setup.tcl->apm_parameter_sync packages/edit-this-page/www/etp-subtopic-create.tcl packages/edit-this-page/ www/etp-subtopic-create.tcl packages/edit-this-page/www/etp-subtopic-create.tcl->apm_parameter_sync ad_parameter_cache ad_parameter_cache (public) apm_parameter_sync->ad_parameter_cache db_list_of_lists db_list_of_lists (public) apm_parameter_sync->db_list_of_lists

Testcases:
No testcase defined.

apm_parameter_unregister (public)

 apm_parameter_unregister [ -callback callback ] \
    [ -package_key package_key ] [ -parameter parameter ] \
    [ -parameter_id parameter_id ] [ parameter_id_legacy ]

Unregisters a parameter from the system.

Switches:
-callback (optional, defaults to "apm_dummy_callback")
-package_key (optional)
-parameter (optional)
-parameter_id (optional)
Parameters:
parameter_id_legacy (optional)
DEPRECATED: previous versions of this proc would specify parameter_id as an unnamed argument. This has now be changed to a flag, but the old syntax is still tolerated in old code. This will generate a warning though and will be dropped in future versions.

Partial Call Graph (max 5 caller/called nodes):
%3 test_parameter__check_procs parameter__check_procs (test acs-tcl) apm_parameter_unregister apm_parameter_unregister test_parameter__check_procs->apm_parameter_unregister test_parameter_register_test parameter_register_test (test acs-tcl) test_parameter_register_test->apm_parameter_unregister ad_parameter_cache ad_parameter_cache (public) apm_parameter_unregister->ad_parameter_cache db_1row db_1row (public) apm_parameter_unregister->db_1row db_exec_plsql db_exec_plsql (public) apm_parameter_unregister->db_exec_plsql db_foreach db_foreach (public) apm_parameter_unregister->db_foreach db_string db_string (public) apm_parameter_unregister->db_string apm_unregister_disinherited_params apm_unregister_disinherited_params (public) apm_unregister_disinherited_params->apm_parameter_unregister boomerang::before-uninstall boomerang::before-uninstall (private) boomerang::before-uninstall->apm_parameter_unregister chat::apm::after_upgrade chat::apm::after_upgrade (private) chat::apm::after_upgrade->apm_parameter_unregister cookieconsent::before-uninstall cookieconsent::before-uninstall (private) cookieconsent::before-uninstall->apm_parameter_unregister packages/acs-admin/www/apm/parameter-delete.tcl packages/acs-admin/ www/apm/parameter-delete.tcl packages/acs-admin/www/apm/parameter-delete.tcl->apm_parameter_unregister

Testcases:
parameter_register_test, parameter__check_procs

apm_parameter_update (public)

 apm_parameter_update [ -callback callback ] parameter_id package_key \
    parameter_name description default_value datatype [ section_name ] \
    [ min_n_values ] [ max_n_values ]
Switches:
-callback (optional, defaults to "apm_dummy_callback")
Parameters:
parameter_id (required)
package_key (required)
parameter_name (required)
description (required)
default_value (required)
datatype (required)
section_name (optional)
min_n_values (optional, defaults to "1")
max_n_values (optional, defaults to "1")
Returns:
The parameter id that has been updated.

Partial Call Graph (max 5 caller/called nodes):
%3 apm_package_upgrade_parameters apm_package_upgrade_parameters (private) apm_parameter_update apm_parameter_update apm_package_upgrade_parameters->apm_parameter_update packages/acs-admin/www/apm/parameter-edit-2.tcl packages/acs-admin/ www/apm/parameter-edit-2.tcl packages/acs-admin/www/apm/parameter-edit-2.tcl->apm_parameter_update db_dml db_dml (public) apm_parameter_update->db_dml

Testcases:
No testcase defined.

apm_pretty_name_for_file_type (public)

 apm_pretty_name_for_file_type type

Returns the pretty name corresponding to a particular file type key

Parameters:
type (required)
Author:
Peter Marklund
See Also:

Partial Call Graph (max 5 caller/called nodes):
%3 packages/acs-admin/www/apm/packages-install-3.tcl packages/acs-admin/ www/apm/packages-install-3.tcl apm_pretty_name_for_file_type apm_pretty_name_for_file_type packages/acs-admin/www/apm/packages-install-3.tcl->apm_pretty_name_for_file_type apm_file_type_names apm_file_type_names (public) apm_pretty_name_for_file_type->apm_file_type_names

Testcases:
No testcase defined.

apm_remove_callback_proc (public)

 apm_remove_callback_proc -type type -package_key package_key

Remove the callback of a certain type for the given package.

Switches:
-type (required)
-package_key (required)
Author:
Peter Marklund

Partial Call Graph (max 5 caller/called nodes):
%3 test_apm__test_callback_get_set apm__test_callback_get_set (test acs-tcl) apm_remove_callback_proc apm_remove_callback_proc test_apm__test_callback_get_set->apm_remove_callback_proc test_apm__test_callback_invoke apm__test_callback_invoke (test acs-tcl) test_apm__test_callback_invoke->apm_remove_callback_proc apm_assert_callback_type_supported apm_assert_callback_type_supported (public) apm_remove_callback_proc->apm_assert_callback_type_supported db_dml db_dml (public) apm_remove_callback_proc->db_dml packages/acs-admin/www/apm/version-callback-delete.tcl packages/acs-admin/ www/apm/version-callback-delete.tcl packages/acs-admin/www/apm/version-callback-delete.tcl->apm_remove_callback_proc

Testcases:
apm__test_callback_get_set, apm__test_callback_invoke

apm_set_callback_proc (public)

 apm_set_callback_proc [ -version_id version_id ] \
    [ -package_key package_key ] -type type proc

Set the name of an APM Tcl procedure callback for a certain package version. Checks if the callback already exists and updates if it does. If version_id is not supplied the id of the currently enabled version of the package will be used.

Switches:
-version_id (optional)
-package_key (optional)
-type (required)
Parameters:
proc (required)
Author:
Peter Marklund
See Also:

Partial Call Graph (max 5 caller/called nodes):
%3 test_apm__test_callback_get_set apm__test_callback_get_set (test acs-tcl) apm_set_callback_proc apm_set_callback_proc test_apm__test_callback_get_set->apm_set_callback_proc test_apm__test_callback_invoke apm__test_callback_invoke (test acs-tcl) test_apm__test_callback_invoke->apm_set_callback_proc apm_assert_callback_type_supported apm_assert_callback_type_supported (public) apm_set_callback_proc->apm_assert_callback_type_supported apm_get_callback_proc apm_get_callback_proc (public) apm_set_callback_proc->apm_get_callback_proc apm_version_id_from_package_key apm_version_id_from_package_key (public) apm_set_callback_proc->apm_version_id_from_package_key db_dml db_dml (public) apm_set_callback_proc->db_dml apm_package_install_callbacks apm_package_install_callbacks (private) apm_package_install_callbacks->apm_set_callback_proc packages/acs-admin/www/apm/version-callback-add-edit.tcl packages/acs-admin/ www/apm/version-callback-add-edit.tcl packages/acs-admin/www/apm/version-callback-add-edit.tcl->apm_set_callback_proc

Testcases:
apm__test_callback_get_set, apm__test_callback_invoke

apm_supported_callback_types (public)

 apm_supported_callback_types

Gets the list of package callback types that are supported by the system. Each callback type represents a certain event or time when a Tcl procedure should be invoked, such as after-install

Author:
Peter Marklund

Partial Call Graph (max 5 caller/called nodes):
%3 test_apm__test_callback_get_set apm__test_callback_get_set (test acs-tcl) apm_supported_callback_types apm_supported_callback_types test_apm__test_callback_get_set->apm_supported_callback_types test_apm__test_callback_invoke apm__test_callback_invoke (test acs-tcl) test_apm__test_callback_invoke->apm_supported_callback_types test_apm__test_info_file apm__test_info_file (test acs-tcl) test_apm__test_info_file->apm_supported_callback_types apm_assert_callback_type_supported apm_assert_callback_type_supported (public) apm_assert_callback_type_supported->apm_supported_callback_types apm_callback_type_supported_p apm_callback_type_supported_p (public) apm_callback_type_supported_p->apm_supported_callback_types apm_read_package_info_file apm_read_package_info_file (public) apm_read_package_info_file->apm_supported_callback_types apm_unused_callback_types apm_unused_callback_types (public) apm_unused_callback_types->apm_supported_callback_types

Testcases:
apm__test_info_file, apm__test_callback_get_set, apm__test_callback_invoke

apm_unused_callback_types (public)

 apm_unused_callback_types -version_id version_id

Get a list enumerating the supported callback types that are not used by the given package version.

Switches:
-version_id (required)

Partial Call Graph (max 5 caller/called nodes):
%3 packages/acs-admin/www/apm/version-callback-add-edit.tcl packages/acs-admin/ www/apm/version-callback-add-edit.tcl apm_unused_callback_types apm_unused_callback_types packages/acs-admin/www/apm/version-callback-add-edit.tcl->apm_unused_callback_types packages/acs-admin/www/apm/version-callbacks.tcl packages/acs-admin/ www/apm/version-callbacks.tcl packages/acs-admin/www/apm/version-callbacks.tcl->apm_unused_callback_types apm_supported_callback_types apm_supported_callback_types (public) apm_unused_callback_types->apm_supported_callback_types db_list db_list (public) apm_unused_callback_types->db_list

Testcases:
No testcase defined.

apm_version_get (public)

 apm_version_get [ -version_id version_id ] \
    [ -package_key package_key ] -array array

Gets information about a package version. TODO: Cache this proc, put it in a namespace and make sure it's used everywhere.

Switches:
-version_id (optional)
The id of the package version to get info for
-package_key (optional)
Can be specified instead of version_id in which case the live version of the package will be used.
-array (required)
The name of the array variable to upvar the info to
Author:
Peter Marklund

Partial Call Graph (max 5 caller/called nodes):
%3 test_acs_system_information_api acs_system_information_api (test acs-tcl) apm_version_get apm_version_get test_acs_system_information_api->apm_version_get test_apm_version_api apm_version_api (test acs-tcl) test_apm_version_api->apm_version_get apm_version_id_from_package_key apm_version_id_from_package_key (public) apm_version_get->apm_version_id_from_package_key db_1row db_1row (public) apm_version_get->db_1row ad_acs_release_date ad_acs_release_date (public) ad_acs_release_date->apm_version_get ad_acs_version ad_acs_version (public) ad_acs_version->apm_version_get

Testcases:
acs_system_information_api, apm_version_api

apm_version_id_from_package_key (public)

 apm_version_id_from_package_key [ -all ] package_key

Return the id of the (per default enabled) version of the given package_key. If no such version id can be found, returns the empty string.

Switches:
-all (optional, boolean)
when specified, return the enabled or disabled version_ids of the package_key.
Parameters:
package_key (required)
Returns:
the supposedly unique version_id for the enabled package, or a list of all the enabled and disabled versions when -all flag is specified
Author:
Peter Marklund

Partial Call Graph (max 5 caller/called nodes):
%3 test_acs_system_information_api acs_system_information_api (test acs-tcl) apm_version_id_from_package_key apm_version_id_from_package_key test_acs_system_information_api->apm_version_id_from_package_key test_apm__test_callback_get_set apm__test_callback_get_set (test acs-tcl) test_apm__test_callback_get_set->apm_version_id_from_package_key test_apm__test_callback_invoke apm__test_callback_invoke (test acs-tcl) test_apm__test_callback_invoke->apm_version_id_from_package_key db_list db_list (public) apm_version_id_from_package_key->db_list db_string db_string (public) apm_version_id_from_package_key->db_string apm::package_version::attributes::get_instance_name apm::package_version::attributes::get_instance_name (private) apm::package_version::attributes::get_instance_name->apm_version_id_from_package_key apm_get_callback_proc apm_get_callback_proc (public) apm_get_callback_proc->apm_version_id_from_package_key apm_package_delete apm_package_delete (public) apm_package_delete->apm_version_id_from_package_key apm_package_install apm_package_install (public) apm_package_install->apm_version_id_from_package_key apm_set_callback_proc apm_set_callback_proc (public) apm_set_callback_proc->apm_version_id_from_package_key

Testcases:
acs_system_information_api, apm__test_callback_get_set, apm__test_callback_invoke

apm_version_info (public)

 apm_version_info version_id

Sets a set of common package information in the caller's environment.

Parameters:
version_id (required)

Partial Call Graph (max 5 caller/called nodes):
%3 apm_package_install_spec apm_package_install_spec (public) apm_version_info apm_version_info apm_package_install_spec->apm_version_info packages/acs-admin/www/apm/package-deinstall.tcl packages/acs-admin/ www/apm/package-deinstall.tcl packages/acs-admin/www/apm/package-deinstall.tcl->apm_version_info packages/acs-admin/www/apm/package-delete-2.tcl packages/acs-admin/ www/apm/package-delete-2.tcl packages/acs-admin/www/apm/package-delete-2.tcl->apm_version_info packages/acs-admin/www/apm/package-delete.tcl packages/acs-admin/ www/apm/package-delete.tcl packages/acs-admin/www/apm/package-delete.tcl->apm_version_info packages/acs-admin/www/apm/package-instances.tcl packages/acs-admin/ www/apm/package-instances.tcl packages/acs-admin/www/apm/package-instances.tcl->apm_version_info db_1row db_1row (public) apm_version_info->db_1row

Testcases:
No testcase defined.

apm_version_installed_p (public)

 apm_version_installed_p version_id
Parameters:
version_id (required)
Returns:
Returns 1 if the specified version_id is installed, 0 otherwise.

Partial Call Graph (max 5 caller/called nodes):
%3 packages/acs-admin/www/apm/package-deinstall.tcl packages/acs-admin/ www/apm/package-deinstall.tcl apm_version_installed_p apm_version_installed_p packages/acs-admin/www/apm/package-deinstall.tcl->apm_version_installed_p packages/acs-admin/www/apm/package-delete-2.tcl packages/acs-admin/ www/apm/package-delete-2.tcl packages/acs-admin/www/apm/package-delete-2.tcl->apm_version_installed_p db_string db_string (public) apm_version_installed_p->db_string

Testcases:
No testcase defined.

apm_version_load_status (public)

 apm_version_load_status version_id

If a version needs to be reloaded (i.e., a -procs.tcl has changed or been added since the version was loaded), returns "needs_reload". If the version has never been loaded, returns "never_loaded". If the version is up-to-date, returns "up_to_date".

Parameters:
version_id (required)

Partial Call Graph (max 5 caller/called nodes):
%3 packages/acs-admin/www/apm/index.tcl packages/acs-admin/ www/apm/index.tcl apm_version_load_status apm_version_load_status packages/acs-admin/www/apm/index.tcl->apm_version_load_status acs_package_root_dir acs_package_root_dir (public) apm_version_load_status->acs_package_root_dir ad_file ad_file (public) apm_version_load_status->ad_file apm_get_package_files apm_get_package_files (public) apm_version_load_status->apm_get_package_files apm_load_tests_p apm_load_tests_p (public) apm_version_load_status->apm_load_tests_p apm_package_key_from_version_id apm_package_key_from_version_id (public) apm_version_load_status->apm_package_key_from_version_id

Testcases:
No testcase defined.

apm_version_loaded_p (public)

 apm_version_loaded_p version_id

Returns 1 if a version of a package has been loaded and initialized, or 0 otherwise.

Parameters:
version_id (required)

Partial Call Graph (max 5 caller/called nodes):
%3

Testcases:
No testcase defined.
[ hide source ] | [ make this the default ]

Content File Source

ad_library {

    Routines used by the package manager.

    @creation-date 13 Apr 2000
    @author Bryan Quinn (bquinn@arsdigita.com)
    @author Jon Salz (jsalz@arsdigita.com)
    @cvs-id $Id: apm-procs.tcl,v 1.118 2024/10/08 14:13:36 antoniop Exp $
}

namespace eval apm {}

#
# Use either "class" or "blueprint" reloading.
#
# Blueprint reloading (starting with OpenACS 5.10) updates the
# blueprint of nsd, which has the consequence the also threads for
# running scheduled procedures can be updated. So far blueprint
# reloading is just tested with NaviServer, but should work with
# AOLserver as well (modulo bugs).
#
#set ::apm::reloading classic
set ::apm::reloading blueprint

#####
# Globals used by the package manager:
#
#     apm_current_package_key
#         Identifies which package is currently being loaded.
#
#
#
# NSV arrays used by the package_manager: (note that all paths are relative
# to [acs_path_root] unless otherwise indicated)
#
#     apm_version_properties($info_file_path)
#
#         Contains a list [list $mtime $properties_array], where $properties_array
#         is a cached copy of the version properties array last returned by
#         [apm_read_package_info_file $info_file_path], and $mtime is the
#         modification time of the $info_file_path when it was last examined.
#
#         This is a cache for apm_read_package_info_file.
#
#     apm_library_mtime($path)
#
#         The modification time of $file (a *-procs.tcl, *-init.tcl or .xql file)
#         when it was last loaded.
#
#     apm_version_procs_loaded_p($version_id)
#     apm_version_init_loaded_p($version_id)
#
#         1 if the *-procs.tcl and *-init.tcl files (respectively) have been
#         loaded for package version $version_id.
#
#     apm_vc_status($path)
#
#         A cached result from apm_fetch_cached_vc_status (of the form
#         [list $mtime $path]) containing the last-known CVS status of
#         $path.
#
#     apm_properties(reload_level)
#
#         The current "reload level" for the server.
#
#     apm_reload($reload_level)
#
#         A list of files which need to be loaded to bring the current interpreter
#         up to reload level $reload_level from level $reload_level - 1.
#
#     apm_reload_watch($path)
#
#         Indicates that $path is a -procs.tcl file which should be examined
#         every time apm_load_any_changed_libraries is invoked, to see whether
#         it has changed since last loaded. The path starts at $::acs::rootdir.
#
# RELOADING VOODOO
#
#     To allow for automatically reloading of Tcl libraries, we introduce the
#     concept of a server-wide "reload level" (starting at zero) stored in
#     the apm_properties(reload_level) NSV array entry. Whenever we determine
#     we want to have all interpreters source a particular -procs.tcl file,
#     we:
#
#         1) Increment apm_properties(reload_level), as a signal to each
#            interpreter that it needs to source some new -procs.tcl files
#            to bring itself up to date.
#         2) Set apm_reload($reload_level), where $reload_level is the new
#            value of apm_properties(reload_level) set in step #1, to the
#            list of files which actually need to be sourced.
#
#     Each interpreter maintains its private, interpreter-specific reload level
#     as a proc named apm_reload_level_in_this_interpreter. Every time the
#     request processor sees a request, it invokes
#     apm_load_any_changed_libraries, which compares the server-wide
#     reload level to the interpreter-private one. If it notes a difference,
#     it reloads the set of files necessary to bring itself up-to-date (i.e.,
#     files noted in the applicable entries of apm_reload).
#
#     Example:
#
#         - The server is started. apm_properties(reload_level) is 0.
#         - I modify /packages/acs-tcl/utilities-procs.tcl.
#         - Through the package manager GUI, I invoke
#           apm_mark_version_for_reload. It notices that utilities-procs.tcl
#           has changed. It increments apm_properties(reload_level) to 1,
#           and sets apm_reload(1) to [list "packages/acs-tcl/utilities-procs.tcl"].
#         - A request is handled in some other interpreter, whose reload
#           level (as returned by apm_reload_level_in_this_interpreter)
#           is 0. apm_load_any_changed_libraries notes that
#           [apm_reload_level_in_this_interpreter] != [nsv_get apm_properties reload_level],
#           so it sources the files listed in apm_reload(1) (i.e., utilities-procs.tcl)
#           and redefines apm_reload_level_in_this_interpreter to return 1.
#
#####


### Callback functions are used to control the logging that occurs during
### the execution of any apm_package that uses the -callback argument.

ad_proc -public apm_dummy_callback { string } {

    A dummy callback routine which does nothing.

} {
    # Do nothing!
}

ad_proc -public apm_ns_write_callback { string } {

    A simple callback which prints out the log message to the server stream.

} {
    ns_write $string
}

ad_proc -public apm_body_callback { string } {
    This callback uses the document API to append more text to the stream.
} {
    append ::__apm_body $string
}


ad_proc apm_callback_and_log { { -severity Notice } callback message } {

    Executes the $callback callback routine with $message as an argument,
    and calls ns_log with the given $severity.

} {
    $callback $message
    ns_log $severity [ad_html_to_text -maxlen 140 -- $message]
}

d_proc -private apm_one_package_descendents {
    package_key
} {

    Returns a list of package keys of all packages that inherit from the given
    package

} {

    foreach descendent [db_list get_descendents {}] {
        if { [info exists ::apm_visited_package_keys($descendent)] } {
            continue
        }
        set ::apm_visited_package_keys($descendent) 1
        lappend ::apm_package_descendents $descendent
        apm_one_package_descendents $descendent
    }

}

ad_proc apm_build_subsite_packages_list {} {

    Build the nsv_set cache of all packages which claim to implement subsite
    semantics.  The kludge to add acs-subsite if it's not declared with the subsite
    attribute set true is needed during the upgrade process ...

} {
    nsv_set apm_subsite_packages_list package_keys {}

    # Make sure old versions work ...
    catch { nsv_set apm_subsite_packages_list package_keys [db_list get_subsites {}] }
    if {"acs-subsite" ni [nsv_get apm_subsite_packages_list package_keys]} {
        nsv_lappend apm_subsite_packages_list package_keys acs-subsite
    }

}

d_proc apm_package_list_url_resolution {
    package_list
} {
    Use a left-right, breadth-first traverse of the inheritance DAG to build a
    structure to be used by the request processor to resolve URLs based on a
    package's "extends" and "embeds" dependencies.
} {

    foreach package $package_list {
        lassign $package package_key dependency_type
        if { [info exists ::apm_visited_package_keys($package_key)] } {
            continue
        }
        switch -- $dependency_type {
            extends -
            "" { lappend ::apm_package_url_resolution $::acs::rootdir/packages/$package_key/www }
            embeds {

                # Reference to an embedded package is through URLs relative to the embedding
                # package's mount point, taking one  of the forms package-key,
                # admin/package-key and sitewide-admin/package-key.  These map to package-key/embed,
                # package-key/embed/admin, and package-key/embed/sitewide-admin respectively.

                # We break references like package-key/admin because such references are unsafe,
                # as the request processor will not perform the expected permission check.

                lappend ::apm_package_url_resolution \
                    [list $::acs::rootdir/packages/$package_key/embed/admin admin/$package_key]
                lappend ::apm_package_url_resolution \
                    [list "" $package_key/admin]

                lappend ::apm_package_url_resolution \
                    [list $::acs::rootdir/packages/$package_key/embed/sitewide-admin \
                         sitewide-admin/$package_key]
                lappend ::apm_package_url_resolution \
                    [list "" $package_key/sitewide-admin]

                lappend ::apm_package_url_resolution \
                    [list $::acs::rootdir/packages/$package_key/embed $package_key]
            }
            default {
                error "apm_package_list_url_resolution: dependency type is $dependency_type"
            }
        }
        set ::apm_visited_package_keys($package_key) 1
    }

    # Make sure old versions work ...
    foreach package $package_list {
        lassign $package package_key dependency_type
        set inherit_templates_p t
        #fix!
        catch { db_1row get_inherit_templates_p {} }
        apm_package_list_url_resolution [db_list_of_lists get_dependencies {}]
    }
}

d_proc apm_one_package_inherit_order {
    package_key
} {

    Returns a list of package keys in package inheritance order.

} {

    if { [info exists ::apm_visited_package_keys($package_key)] } {
        return
    }
    set ::apm_visited_package_keys($package_key) 1

    foreach dependency [db_list get_dependencies {}] {
        apm_one_package_inherit_order $dependency
    }

    lappend ::apm_package_inherit_order $package_key
}

d_proc -private apm_one_package_load_libraries_dependencies {
    package_key
} {

    Generate a list of package keys in library load dependency order.

} {

    if { [info exists ::apm_visited_package_keys($package_key)] } {
        return
    }
    set ::apm_visited_package_keys($package_key) 1
    set package_key_list ""

    foreach dependency [db_list get_dependencies {}] {
        apm_one_package_load_libraries_dependencies $dependency
    }
    lappend ::apm_package_load_libraries_order $package_key
}

d_proc apm_build_one_package_relationships {
    package_key
} {

    Builds the nsv dependency structures for a single package.

} {

    unset -nocomplain ::apm_visited_package_keys
    set ::apm_package_url_resolution [list]
    apm_package_list_url_resolution $package_key
    nsv_set apm_package_url_resolution $package_key $::apm_package_url_resolution

    unset -nocomplain ::apm_visited_package_keys
    set ::apm_package_inherit_order [list]
    apm_one_package_inherit_order $package_key
    nsv_set apm_package_inherit_order $package_key $::apm_package_inherit_order

    unset -nocomplain ::apm_visited_package_keys
    set ::apm_package_load_libraries_order [list]
    apm_one_package_load_libraries_dependencies $package_key
    nsv_set apm_package_load_libraries_order $package_key $::apm_package_load_libraries_order

    unset -nocomplain ::apm_visited_package_keys
    set ::apm_package_descendents [list]
    apm_one_package_descendents $package_key
    nsv_set apm_package_descendents $package_key $::apm_package_descendents

}

ad_proc apm_build_package_relationships {} {

    Builds the nsv dependency and ancestor structures.

} {
    foreach package_key [apm_enabled_packages] {
        apm_build_one_package_relationships $package_key
    }
}

d_proc apm_package_descendents {
    package_key
} {
    Wrapper that returns the cached package descendents list.
} {
    return [nsv_get apm_package_descendents $package_key]
}

d_proc apm_package_inherit_order {
    package_key
} {
    Wrapper that returns the cached package inheritance order list.
} {
    return [nsv_get apm_package_inherit_order $package_key]
}

d_proc apm_package_url_resolution {
    package_key
} {
    Wrapper that returns the cached package search order list.
} {
    return [nsv_get apm_package_url_resolution $package_key]
}

d_proc apm_package_load_libraries_order {
    package_key
} {
    Wrapper that returns the cached package library load order list.
} {
    return [nsv_get apm_package_load_libraries_order $package_key]
}

d_proc -private apm_package_singleton_p {
    package_key
} {
    @return boolean telling whether a package is a singleton or not
} {
    return [acs::per_thread_cache eval -key acs-tcl.apm-singleton-$package_key {
        db_string check_singleton {
            select singleton_p from apm_package_types
            where package_key = :package_key
        } -default f
    }]
}

ad_proc -public apm_version_loaded_p { version_id } {

    Returns 1 if a version of a package has been loaded and initialized, or 0 otherwise.

} {
    return [nsv_exists apm_version_init_loaded_p $version_id]
}

d_proc -public apm_mark_files_for_reload {
    {-force_reload:boolean}
    file_list
} {
    Mark the given list of Tcl and query files for reload in all
    interpreters. Only marks files for reload if they haven't been
    loaded before or they have changed since last reload.

    @param file_list A list of paths relative to $::acs::rootdir
    @param force_reload Mark the files for reload even if their modification
    time in the nsv cache doesn't differ from the one
    in the filesystem.

    @return The list of files marked for reload.

    @author Peter Marklund
} {
    set changed_files [list]
    foreach relative_path $file_list {
        set full_path "$::acs::rootdir/$relative_path"

        # If the file exists, and either has never been loaded or has an mtime
        # which differs the mtime it had when last loaded, mark to be loaded.
        if { [ad_file isfile $full_path] } {
            set mtime [ad_file mtime $full_path]
            if { $force_reload_p
                 || (![nsv_exists apm_library_mtime $relative_path]
                     || [nsv_get apm_library_mtime $relative_path] != $mtime
                     || [clock seconds]-$mtime < 5) } {
                lappend changed_files $relative_path
            }
        }
    }

    if {$::apm::reloading eq "classic"} {
        if { [llength $changed_files] > 0 } {
            set reload [nsv_incr apm_properties reload_level]
            nsv_set apm_reload $reload $changed_files
        }
    }

    return $changed_files
}

proc ::foo0 {} {return 0}

d_proc -public apm_mark_version_for_reload {
    version_id
    { changed_files_var "" }
} {
    Examines all tcl_procs files in package version $version_idif any have
    changed since they were loaded, marks (in the apm_reload array) that
    they must be reloaded by each Tcl interpreter (using the
    apm_load_any_changed_libraries procedure).

    <p>Saves a list of files that have changed (and thus marked to be reloaded) in
    the variable named <code>$file_info_var</code>, if provided. Each element
    of this list is of the form:

    <blockquote><pre>[list $file_id $path]</pre></blockquote>

} {
    if { $changed_files_var ne "" } {
        upvar $changed_files_var changed_files
    }
    set package_key [apm_package_key_from_version_id $version_id]
    #ns_log notice "apm_mark_version_for_reload $package_key version_id $version_id"
    set changed_files [list]

    set file_types [list tcl_procs query_file]
    if { [apm_load_tests_p] } {
        lappend file_types test_procs
    }

    foreach path [apm_get_package_files -package_key $package_key -file_types $file_types] {
        set full_path "[acs_package_root_dir $package_key]/$path"
        set relative_path "packages/$package_key/$path"

        set reload_file [apm_mark_files_for_reload $relative_path]
        if { [llength $reload_file] > 0 } {
            # The file marked for reload
            lappend changed_files $relative_path
        }
    }
    return $changed_files
}

ad_proc -public apm_version_load_status { version_id } {

    If a version needs to be reloaded (i.e., a <code>-procs.tcl</code> has changed
                                       or been added since the version was loaded), returns "needs_reload".
    If the version has never been loaded, returns "never_loaded". If the
    version is up-to-date, returns "up_to_date".

} {
    # See if the version was ever loaded.
    if { ![apm_package_version_enabled_p $version_id] } {
        return "never_loaded"
    }

    set package_key [apm_package_key_from_version_id $version_id]
    set procs_types [list tcl_procs]
    if { [apm_load_tests_p] } {
        lappend procs_types test_procs
    }
    foreach file [apm_get_package_files -package_key $package_key -file_types $procs_types] {
        # If $file has never been loaded, i.e., it has been added to the version
        # since the version was initially loaded, return needs_reload.
        if { ![nsv_exists apm_library_mtime "packages/$package_key/$file"] } {
            return "needs_reload"
        }

        set full_path "[acs_package_root_dir $package_key]/$file"
        # If $file had a different mtime when it was last loaded, return
        # needs_reload. (If the file should exist but doesn't, just skip it.)
        if { [ad_file exists $full_path]
             &&  [ad_file mtime $full_path] ne [nsv_get apm_library_mtime "packages/$package_key/$file"]
         } {
            return "needs_reload"
        }
    }

    foreach file [apm_get_package_files -package_key $package_key -file_types "query_file"] {
        # If $file has never been loaded, i.e., it has been added to the version
        # since the version was initially loaded, return needs_reload.
        if { ![nsv_exists apm_library_mtime "packages/$package_key/$file"] } {
            return "needs_reload"
        }

        set full_path "[acs_package_root_dir $package_key]/$file"
        # If $file had a different mtime when it was last loaded, return
        # needs_reload. (If the file should exist but doesn't, just skip it.)
        if { [ad_file exists $full_path]
             && [ad_file mtime $full_path] ne [nsv_get apm_library_mtime "packages/$package_key/$file"]
         } {
            return "needs_reload"
        }
    }

    return "up_to_date"
}

d_proc -private apm_load_libraries {
    {-force_reload:boolean 0}
    {-packages {}}
    {-callback apm_dummy_callback}
    {-procs:boolean}
    {-init:boolean}
    {-test_procs:boolean}
    {-test_init:boolean}
} {

    Loads all -procs.tcl (if $procs_or_init is "procs") or -init.tcl  files into the
    current interpreter for installed, enabled packages. Only loads
    files which have not yet been loaded. This is intended to be called only during server
    initialization, since it loads libraries only into the running interpreter, as opposed
    to in *all* active interpreters.

} {
    set file_types [list]
    if { $procs_p } {
        lappend file_types tcl_procs
    }
    if { $init_p } {
        lappend file_types tcl_init
    }
    if { $test_procs_p } {
        lappend file_types test_procs
    }
    if { $test_init_p } {
        lappend file_types test_init
    }

    if { $packages eq "" } {
        set packages [apm_enabled_packages]
    }

    # Scan the package directory for files to source.
    set files [list]
    foreach package $packages {

        set paths [apm_get_package_files -package_key $package -file_types $file_types]

        foreach path [lsort $paths] {
            lappend files [list $package $path]
        }
    }

    # Release all outstanding database handles (since the file we're sourcing
    # might be using the ns_db database API as opposed to the new db_* API).
    db_release_unused_handles
    apm_files_load -force_reload=$force_reload_p -callback $callback $files
}

ad_proc -public apm_load_tests_p {} {
    Determine whether to load acs-automated-testing tests
    for packages.

    @return 1 if tests should be loaded and 0 otherwise

    @author Peter Marklund
} {
    return [apm_package_enabled_p "acs-automated-testing"]
}

d_proc -public apm_load_packages {
    {-force_reload:boolean 0}
    {-load_libraries_p 1}
    {-load_queries_p 1}
    {-packages {}}
} {
    Load Tcl libraries and queries for the packages with given
    keys into the current interpreter. Will load Tcl
    tests when the acs-automated-testing package is enabled.

    @param force_reload Reload Tcl libraries even if they are already loaded.
    @param load_libraries_p Switch to indicate if Tcl libraries in (-procs.tcl and -init.tcl)
                            files should be loaded. Defaults to true.
    @param load_queries_p   Switch to indicate if xql query files should be loaded. Default true.
    @param packages     A list of package_keys for packages to be loaded. Defaults to
                        all enabled packages.  These packages, along with the packages
                        they depend on, will be loaded in dependency-order using the
                        information provided via the "provides" and "requires" definitions.

    @see apm_mark_version_for_reload

    @author Peter Marklund
} {
    set enabled_packages [apm_enabled_packages]
    if { $packages eq "" } {
        set packages $enabled_packages
    }

    set packages_to_load [list]
    foreach package_key $packages {
        foreach package_to_load [::apm_package_load_libraries_order $package_key] {
            #
            # Never add packages, which are not enabled.
            #
            if {$package_to_load ni $packages_to_load && $package_to_load in $enabled_packages} {
                lappend packages_to_load $package_to_load
            }
        }
    }

    # Should acs-automated-testing tests be loaded?
    set load_tests_p [apm_load_tests_p]

    # Load *-procs.tcl files
    if { $load_libraries_p } {
        apm_load_libraries -force_reload=$force_reload_p -packages $packages_to_load -procs
    }

    # Load up the Queries (OpenACS, ben@mit.edu)
    if { $load_queries_p } {
        apm_load_queries -packages $packages_to_load
    }

    # Load up the Automated Tests and associated Queries if necessary
    if {$load_tests_p} {
        apm_load_libraries -force_reload=$force_reload_p -packages $packages -test_procs
        apm_load_queries -packages $packages_to_load -test_queries
    }

    if { $load_libraries_p } {
        # branimir: acs-lang needs to be initialized before anything else
        # because there are packages whose *-init.tcl files depend on it.
        apm_load_libraries -force_reload=$force_reload_p -init -packages acs-lang
        set p [lsearch $packages_to_load acs-lang]
        if {$p > -1} {
            set unique_packages [lreplace $packages_to_load $p $p]
        } else {
            set unique_packages $packages_to_load
        }
        apm_load_libraries -force_reload=$force_reload_p -init -packages $unique_packages
    }

    # Load up the Automated Tests initialization scripts if necessary
    if {$load_tests_p} {
        apm_load_libraries -force_reload=$force_reload_p -packages $packages_to_load -test_init
    }
}

d_proc -private apm_load_queries {
    {-packages {}}
    {-callback apm_dummy_callback}
    {-test_queries:boolean}
} {
    Load up the queries for all enabled packages
    (or all specified packages). Follows the pattern
    of the load_libraries proc, but only loads query information

    @param packages Optional list of keys for packages to load queries for.

    @author ben@mit.edu
} {
    if { $packages eq "" } {
        set packages [apm_enabled_packages]
    }

    # Scan the package directory for files to source.
    set files [list]
    foreach package $packages {

        set files [ad_find_all_files $::acs::rootdir/packages/$package]
        if { [llength $files] == 0 } {
            ns_log Error "apm_load_queries: Unable to locate $::acs::rootdir/packages/$package/*. when scanning for SQL queries to load."
        }

        set testdir    "$::acs::rootdir/packages/$package/tcl/test"
        set testlength [string length $testdir]

        foreach file [lsort $files] {

            set file_db_type [apm_guess_db_type $package $file]
            set file_type [apm_guess_file_type $package $file]

            if {![string compare -length $testlength $testdir $file]} {
                set is_test_file_p 1
            } else {
                set is_test_file_p 0
            }

            #
            # Note this exclusive or represents the following:
            # test_queries_p - Load normal xql files or load test xql files
            # is_test_file_p - Current file is a test file or not.
            #
            # !(test_queries_p ^ is_test_file_p)  = Load it or not?
            #             !( 0 ^ 0 )             = Yep
            #             !( 0 ^ 1 )             = Nope
            #             !( 1 ^ 0 )             = Nope
            #             !( 1 ^ 1 )             = Yep
            #
            if {!($test_queries_p ^ $is_test_file_p)
                && $file_type eq "query_file"
                && ($file_db_type eq "" || $file_db_type eq [db_type])
            } {
                db_qd_load_query_file $file
            }
        }
    }
    ns_log debug "apm_load_queries: DONE looping through files from which to load queries"
}

ad_proc -private apm_subdirs { path } {

    Returns a list of subdirectories of path (including path itself)

} {
    set dirs [list]
    lappend dirs $path
    foreach subdir [glob -nocomplain -type d [ad_file join $path *]] {
        lappend dirs {*}[apm_subdirs $subdir]
    }
    return $dirs
}

ad_proc -public apm_pretty_name_for_file_type { type } {

    Returns the pretty name corresponding to a particular file type key

    @see apm_file_type_names

    @author Peter Marklund
} {
    array set file_type_names [apm_file_type_names]

    return $file_type_names($type)
}

ad_proc -private apm_get_changed_watched_files {} {

    Check, which of the watched files have to be reloaded

    @return list of filenames
} {
    set files_to_reload [list]
    foreach file [nsv_array names apm_reload_watch] {
        set path "$::acs::rootdir/$file"
        ns_log Debug "APM: File being watched: $path"

        if { [ad_file exists $path]
             && (![nsv_exists apm_library_mtime $file]
                 || [ad_file mtime $path] ne [nsv_get apm_library_mtime $file])
         } {
            lappend files_to_reload $file
        }
    }
    if {[llength $files_to_reload] > 0} {
        if {[llength $files_to_reload] > 1} {
            lassign {s have} suffix verb
        } else {
            lassign {{} has} suffix verb
        }
        ns_log Notice "apm_reloads: Watched file$suffix [join $files_to_reload ""] $verb changed"
    }

    return $files_to_reload
}

d_proc -public apm_load_any_changed_libraries {
    {-version_files ""}
    {errorVarName {}}
} {

    In the running interpreter, reloads files marked for reload by
    apm_mark_version_for_reload. If any watches are set, examines watched
    files to see whether they need to be reloaded as well. This is intended
    to be called only by the request processor (since it should be invoked
    before any filters or registered procedures are applied).

} {
    set files $version_files

    if {$errorVarName ne ""} {
        upvar $errorVarName errors
    } else {
        array set errors [list]
    }

    if {$::apm::reloading eq "blueprint"} {
        #ns_log notice "### blueprint_reloading: apm_load_any_changed_libraries [time {apm_get_changed_watched_files}]"

        #
        # Add the watched files, but don't load these if these are
        # already included.
        #
        foreach file [apm_get_changed_watched_files] {
            if {$file ni $files} {
                lappend files $file
            }
        }
        if {[llength $files] > 0} {
            ns_log notice "### blueprint_reloading: [llength $files] files $files"
            #::xo::broadcast send {ns_ictl markfordelete}
            #
            # Transform files into reload-cmds
            #
            set cmds [apm_package_reload_cmds $files]
            #
            # Execute these cmds in a fresh interp to produce a new
            # blueprint.
            #
            set before [list epoch [ns_ictl epoch] size [string length [ns_ictl get]]]
            ns_log notice "### blueprint_reloading: before $before cmds:\n[join $cmds \;\n]"

            ns_eval [join $cmds \;]
            #
            # The current thread has still the old blueprint. If we
            # would modify the naviserver sources, it would be simple
            # the show the diffs. here, it is more involved. The see
            # the effect in size on the blueprint, we have to run the
            # change statistics in a fresh thread.  Let us hope that
            # the ns_job thread update is not deferred by "ns_ictl
            # maxconcurrentupdates", so we report as well the
            # epoch. If there is a new epoch shown, one can be sure
            # that we see the updated size. Otherwise, one will see
            # this on the next reload in the log file.
            #
            ns_job queue ns_eval_q:[ns_info server] [subst -nocommands {
                #
                # Warning: Avoid dollar-substitution here, unless
                # wanted at job registration time.
                #
                set blueprint [ns_ictl get]
                set after [list epoch [ns_ictl epoch] size [string length [set blueprint]]]
                set diff [expr {[dict get [set after] size] - [dict get {$before} size]}]
                ns_log notice "### blueprint_reloading: after [set after] diff [set diff]"
                if {0 && [set diff] != 0} {
                    set F [open /tmp/__blueprint.[clock seconds] w]
                    puts [set F] [set blueprint]
                    close [set F]
                }
            }]
        }
    }

    if {$::apm::reloading eq "classic"} {

        #ns_log notice "### classic_reloading: apm_load_any_changed_libraries"

        #
        # Determine the current reload level in this interpreter by
        # calling apm_reload_level_in_this_interpreter. If this fails, we
        # define the reload level to be zero.
        #
        if { [catch { set reload_level [apm_reload_level_in_this_interpreter] } error] } {
            proc apm_reload_level_in_this_interpreter {} { return 0 }
            set reload_level 0
        }

        #
        # Check watched files, adding them to files_to_reload if they have
        # changed.
        #
        set files_to_reload [apm_get_changed_watched_files]

        #
        # If there are any changed watched files, stick another entry on
        # the reload queue.
        #
        if { [llength $files_to_reload] > 0 } {
            ns_log Notice "apm_load_any_changed_libraries: Reloading [join $files_to_reload {, }]"
            set new_level [nsv_incr apm_properties reload_level]
            nsv_set apm_reload $new_level $files_to_reload
        }

        set changed_reload_level_p 0

        # Keep track of which files we've reloaded in this loop so we never
        # reload the same one twice.
        while { $reload_level < [nsv_get apm_properties reload_level] } {
            incr reload_level
            set changed_reload_level_p 1
            # If there's no entry in apm_reload for that reload level, back out.
            if { ![nsv_exists apm_reload $reload_level] } {
                incr reload_level -1
                break
            }
            set reload_cmds [apm_package_reload_cmds [nsv_get apm_reload $reload_level]]
            foreach cmd $reload_cmds {
                if {$cmd ne ""} {
                    ns_log notice "### apm classic reload level $reload_level: cmd $cmd"
                    {*}$cmd
                }
            }
        }

        # We changed the reload level in this interpreter, so redefine the
        # apm_reload_level_in_this_interpreter proc.
        #
        if { $changed_reload_level_p } {
            proc apm_reload_level_in_this_interpreter {} "return $reload_level"
        }
    }
}

ad_proc -private apm_package_reload_cmds {files} {

    Map filenames into reloading cmds. For every file, a loading
    command is appended to the result. The command might be empty.

    @return list of Tcl cmds to be executed to load these files.

} {
    set cmds {}
    if { [llength $files] > 0 } {
        ns_log Notice "apm_reload: Reloading *-procs.tcl amd .xql files in this interpreter..."
    }

    foreach file $files {
        set cmd {}
        #
        # If we haven't yet reloaded the file in this loop, source it.
        #
        if { ![info exists reloaded_files($file)] } {
            # File is usually of form packages/package_key
            set file_path "$::acs::rootdir/$file"
            set file_ext [ad_file extension $file_path]
            switch -- $file_ext {
                .tcl {
                    # Make sure this is not a -init.tcl file as those should only be sourced on server startup
                    if { ![string match "*-init.tcl" $file_path] } {
                        ns_log Notice "apm: Reloading $file..."
                        set cmd [list apm_source $file_path errors]
                    }
                }
                .xql {
                    ns_log Notice "apm: Reloading $file..."
                    set cmd [list db_qd_load_query_file $file_path errors]
                }
                default {
                    ns_log Notice "apm: File $file_path has unknown extension. Not reloading."
                }
            }
            set reloaded_files($file) 1
        }
        lappend cmds $cmd
    }
    return $cmds
}


ad_proc -private apm_package_version_release_tag { package_key version_name } {

    Returns a CVS release tag for a particular package key and version name.

} {
    regsub -all -- {\.} [string toupper "$package_key-$version_name""-" release_tag
    return $release_tag
}

ad_proc -public apm_package_parameters {package_key} {
    @return A list of all the package parameter names.
} {
    return [db_list get_names {
        select parameter_name from apm_parameters
        where package_key = :package_key
    }]
}

d_proc -public apm_package_supported_databases {
    package_key
} {
    Return a list of db types (i.e. oracle, postgresql)
    supported by the package with given key.

    @author Peter Marklund

    @see db_known_database_types
    @see apm_package_supports_rdbms_p
} {
    set supported_databases_list [list]
    foreach db_type_info [db_known_database_types] {
        set db_type [lindex $db_type_info 0]
        if { [apm_package_supports_rdbms_p -package_key $package_key] } {
            lappend supported_databases_list $db_type
        }
    }

    return $supported_databases_list
}

d_proc -public apm_package_registered_p {
    package_key
} {
    Returns 1 if there is a registered package with the indicated package_key.
    Returns 0 otherwise.
} {
    ### Query the database for the indicated package_key
    return [db_0or1row apm_package_registered_p {
        select 1 from apm_package_types
        where package_key = :package_key
    }]
}

d_proc -public apm_package_installed_p {
    package_key
} {
    Returns 1 if there is an installed package version corresponding to the package_key,
    0 otherwise. Uses a cached value for performance.
} {
    acs::try_cache ::acs::misc_cache eval apm_package_installed-$package_key {
        db_0or1row apm_package_installed_p {
            select 1 from apm_package_versions
            where package_key = :package_key
            and installed_p = 't'
        }
    }
}

d_proc -public apm_package_enabled_p {
    package_key
} {
    Returns 1 if there is an enabled package version corresponding to the package_key
    and 0 otherwise.
} {
    acs::try_cache ::acs::misc_cache eval -per_request apm_package_enabled-$package_key {
        db_0or1row apm_package_enabled_p {
            select 1 from apm_package_versions
            where package_key = :package_key
            and enabled_p = 't'
        }
    }
}

ad_proc -public apm_enabled_packages {} {
    Returns a list of package_key's for all enabled packages.

    @author Peter Marklund
} {
    return [db_list enabled_packages {}]
}


d_proc -public apm_version_installed_p {
    version_id
} {
    @return Returns 1 if the specified version_id is installed, 0 otherwise.
} {
    return [db_string apm_version_installed_p {} -default 0]
}

ad_proc -public apm_highest_version {package_key} {
    Return the highest version of the indicated package.
    @return the version_id of the highest installed version of a package.
} {
    return [acs::dc call apm_package highest_version -package_key $package_key]
}

ad_proc -public apm_highest_version_name {package_key} {
    Return the highest version of the indicated package.
    @return the version_name of the highest installed version of a package.
} {
    return [db_string apm_highest_version_name {} -default ""]
}

ad_proc -public apm_num_instances {package_key} {

    @return The number of instances of the indicated package.
} {
    return [db_string query {
        select count(*) from apm_packages
        where package_key = :package_key
    }]
}

d_proc -public apm_parameter_update {
    {-callback apm_dummy_callback}
    parameter_id
    package_key
    parameter_name
    description
    default_value
    datatype
    {section_name ""}
    {min_n_values 1}
    {max_n_values 1}
} {
    @return The parameter id that has been updated.
} {
    db_dml parameter_update {
        update apm_parameters
        set parameter_name = :parameter_name,
        default_value  = :default_value,
        datatype       = :datatype,
        description       = :description,
        section_name   = :section_name,
        min_n_values   = :min_n_values,
        max_n_values   = :max_n_values
        where parameter_id = :parameter_id
    }

    db_dml object_title_update {
        update acs_objects
        set title = :parameter_name
        where object_id = :parameter_id
    }

    return $parameter_id
}

d_proc -public apm_parameter_register {
    {-callback apm_dummy_callback}
    {-parameter_id ""}
    {-scope instance}
    parameter_name
    description
    package_key
    default_value
    datatype
    {section_name ""}
    {min_n_values 1}
    {max_n_values 1}
} {
    Register a parameter in the system.

    The new "scope" parameter is named rather than positional to avoid breaking existing
    code.

    @return The parameter id of the new parameter.

} {
    ns_log debug "apm_parameter_register: Registering $parameter_name$section_name$default_value"

    set parameter_id [db_exec_plsql parameter_register {}]

    # Propagate to descendents if it's an instance parameter.

    if { $scope eq "instance" } {
        apm_copy_param_to_descendents $package_key $parameter_name
    }

    return $parameter_id
}

d_proc -public apm_parameter_unregister {
    {-callback apm_dummy_callback}
    {-package_key ""}
    {-parameter ""}
    {-parameter_id ""}
    {parameter_id_legacy ""}
} {
    Unregisters a parameter from the system.

    @param parameter_id_legacy DEPRECATED: previous versions of this
                               proc would specify parameter_id as an
                               unnamed argument. This has now be
                               changed to a flag, but the old syntax
                               is still tolerated in old code. This
                               will generate a warning though and will
                               be dropped in future versions.
} {
    # Transitional code to support legacy definition of parameter_id
    # specified as an unnamed argument.
    if {$parameter_id_legacy ne "" &&
        $parameter_id eq ""
    } {
        set parameter_id $parameter_id_legacy
        ns_log warning "apm_parameter_unregister: use of unnamed argument is deprecated for this proc, please use -parameter_id flag"
    }

    if { $parameter_id eq "" } {
        set parameter_id [db_string select_parameter_id {
            select parameter_id
            from apm_parameters
            where package_key = :package_key
            and parameter_name = :parameter
        }]
    }

    db_1row get_scope_and_name {
        select scope, parameter_name
        from apm_parameters
        where parameter_id = :parameter_id
    }

    ns_log Debug "apm_parameter_unregister: Unregistering parameter $parameter_id."

    if { $scope eq "global" } {
        ad_parameter_cache -delete $package_key $parameter_name
    } else {
        db_foreach all_parameters_packages {} {
            ad_parameter_cache -delete $package_id $parameter_name
        }
    }
    db_exec_plsql unregister {}
}

d_proc -public apm_dependency_add {
    {-callback apm_dummy_callback}
    {-dependency_id ""}
    dependency_type
    version_id
    dependency_uri
    dependency_version
} {
    Add a dependency to a version.
    @return The id of the new dependency.
} {
    return [db_exec_plsql dependency_add {}]
}

ad_proc -public apm_dependency_remove {dependency_id} {

    Removes a dependency from the system.

} {
    db_exec_plsql dependency_remove {}
}

d_proc -public apm_interface_add {
    {-callback apm_dummy_callback}
    {-interface_id ""}
    version_id
    interface_uri
    interface_version
} {

    Add a interface to a version.
    @return The id of the new interface.
} {
    return [db_exec_plsql interface_add {}]
}

ad_proc -public apm_interface_remove {interface_id} {

    Removes a interface from the system.

} {
    db_exec_plsql interface_remove {}
}

d_proc -public apm_version_get {
    {-version_id ""}
    {-package_key ""}
    {-array:required}
} {
    Gets information about a package version. TODO: Cache this proc, put it in
    a namespace and make sure it's used everywhere.

    @param version_id The id of the package version to get info for
    @param package_key Can be specified instead of version_id in which case
    the live version of the package will be used.
    @param array      The name of the array variable to upvar the info to

    @author Peter Marklund
} {
    upvar $array row

    if { $package_key ne "" } {
        set version_id [apm_version_id_from_package_key $package_key]
    }

    db_1row select_version_info {} -column_array row
}

namespace eval ::acs {}
#
# package_id -> package_key
#

ad_proc -public apm_package_key_from_id {package_id} {
    @return The package key of the instance.
} {
    return [acs::per_thread_cache eval -key acs-tcl.apm_package_key_from_id($package_id) {
        db_string apm_package_key_from_id {
            select package_key from apm_packages where package_id = :package_id
        } -default ""
    }]
}

#
# package_id -> instance_name
#

ad_proc -public apm_instance_name_from_id {package_id} {
    @return The name of the instance.
} {
    return [util_memoize [list apm_instance_name_from_id_not_cached $package_id]]
}

ad_proc -private apm_instance_name_from_id_not_cached {package_id} {
    unmemoized version of apm_instance_name_from_id
} {
    return [db_string apm_package_instance_name_from_id {
        select instance_name from apm_packages where package_id = :package_id
    } -default ""]
}


#
# package_key -> package_id
#

ad_proc -public apm_package_id_from_key {package_key} {
    @return The package id of the instance of the package.
    0 if no instance exists, error if several instances exist.
} {
    set var ::apm::package_id_from_key($package_key)
    if {[info exists $var]} {return [set $var]}
    set result [util_memoize [list apm_package_id_from_key_not_cached $package_key]]
    #set result [ns_cache_eval ns:memoize apm_package_id_from_key_$package_key [list apm_package_id_from_key_not_cached $package_key]]
    if {$result != 0} {
        set $var $result
    }
    return $result
}

ad_proc -public apm_flush_package_id_cache {package_key} {
    Flush the package id cache for this package at least in the
    current thread.  TODO: should be refactored together with the
    2level cache (per thread and util_memoize).
} {
    unset -nocomplain ::apm::package_id_from_key($package_key)
    util_memoize_flush [list apm_package_id_from_key_not_cached $package_key]
}

ad_proc -private apm_package_id_from_key_not_cached {package_key} {
    DB accessing version of apm_package_id_from_key.
} {
    return [db_string apm_package_id_from_key {
        select package_id from apm_packages where package_key = :package_key
    } -default 0]
}

d_proc -public apm_package_ids_from_key {
    -package_key:required
    -mounted:boolean
} {
    @param package_key The package key we are looking for the package
    @param mounted Does the package have to be mounted?

    @return List of package ids of all instances of the package.
    Empty string
} {
    return [util_memoize [list apm_package_ids_from_key_not_cached -package_key $package_key -mounted_p $mounted_p]]
}

d_proc -private apm_package_ids_from_key_not_cached {
    -package_key:required
    {-mounted_p "0"}
} {
    unmemoized version of apm_package_ids_from_key
} {

    if {$mounted_p} {
        set package_ids [list]
        db_foreach apm_package_ids_from_key {
            select package_id from apm_packages where package_key = :package_key
        } {
            if {"" ne [site_node::get_node_id_from_object_id -object_id $package_id] } {
                lappend package_ids $package_id
            }
        }
        return $package_ids
    } else {
        return [db_list apm_package_ids_from_key {
            select package_id from apm_packages where package_key = :package_key
        }]
    }
}

#
# package_id -> package_url
#

ad_proc -public apm_package_url_from_id {package_id} {
    Will return the first url found for a given package_id

    @return The package url of the instance of the package.
} {
    return [lindex [site_node::get_url_from_object_id -object_id $package_id] 0]
}

#
# package_key -> package_url
#

ad_proc -public apm_package_url_from_key {package_key} {
    @return The package url of the instance of the package.
    only valid for singleton packages.
} {
    return [apm_package_url_from_id [apm_package_id_from_key $package_key]]
}

#
# package_key -> version_id
#

d_proc -public apm_version_id_from_package_key {
    {-all:boolean}
    package_key
} {
    Return the id of the (per default enabled) version of the given package_key.
    If no such version id can be found, returns the empty string.

    @param all when specified, return the enabled or disabled version_ids of the package_key.
    @param package_key
    @author Peter Marklund

    @return the supposedly unique version_id for the enabled package, or a list of
            all the enabled and disabled versions when -all flag is specified
} {
    if {$all_p} {
        return [db_list get_id {}]
    } else {
        return [db_string get_enabled_id {} -default ""]
    }
}

#
# version_id -> package_key
#

ad_proc -public apm_package_key_from_version_id {version_id} {
    Returns the package_key for the given APM package version id. Goes to the database
    the first time called and then uses a cached value. Calls the proc apm_package_key_from_version_id_mem.

    @author Peter Marklund (peter@collaboraid.biz)
} {
    return [util_memoize [list apm_package_key_from_version_id_not_cached $version_id]]

}

ad_proc -private apm_package_key_from_version_id_not_cached {version_id} {
    Returns the package_key for the given APM package version id. Goes to the database
    every time called.

    @author Peter Marklund (peter@collaboraid.biz)
} {
    return [db_string apm_package_id_from_key {
        select package_key from apm_package_version_info where version_id = :version_id
    } -default 0]
}

ad_proc -public apm_version_info {version_id} {

    Sets a set of common package information in the caller's environment.

} {

    uplevel 1 {
        db_1row apm_package_by_version_id {
            select pretty_name, version_name, package_key, installed_p, distribution_uri, tagged_p
            from apm_package_version_info where version_id = :version_id
        }
    }
}

ad_proc -public apm_package_version_installed_p {package_key version_name} {

    @return 1 if the indicated package version is installed, 0 otherwise.

} {
    return [db_0or1row apm_package_version_installed_p {
        select 1 from apm_package_versions
         where package_key  = :package_key
           and version_name = :version_name
    }]
}

ad_proc -public apm_package_version_enabled_p {version_id} {

    @return 1 if the indicated package version is installed, 0 otherwise.

} {
    return [db_string apm_package_version_enabled_p {}]
}


ad_proc -private apm_post_instantiation_tcl_proc_from_key { package_key } {
    Generates the name of the Tcl procedure we execute for
    post-instantiation.

    @author Michael Bryzek (mbryzek@arsdigita.com)
    @creation-date 2001-03-05

    @return The name of a Tcl procedure, if it exists, or empty string
    if no such Tcl procedure was found.
} {
    set procedure_name [string tolower "[string trim $package_key]_post_instantiation"]
    # Change all "-" to "_" to mimic our Tcl standards
    regsub -all -- {\-} $procedure_name "_" procedure_name
    if { [namespace which ::$procedure_name] eq "" } {
        # No such procedure exists...
        return ""
    }
    # Procedure exists
    return $procedure_name
}


d_proc -public apm_package_rename {
    {-package_id ""}
    {-instance_name:required}
} {
    Renames a package instance
} {
    if { $package_id eq "" } {
        set package_id [ad_conn package_id]
    }
    db_transaction {
        db_dml app_rename {
            update apm_packages
            set instance_name = :instance_name
            where package_id = :package_id
        }
        db_dml rename_acs_object {
            update acs_objects
            set title = :instance_name
            where object_id = :package_id
        }
    }
    foreach node_id [db_list nodes_to_sync {}] {
        site_node::update_cache -node_id $node_id
    }
}

d_proc -public apm_set_callback_proc {
    {-version_id ""}
    {-package_key ""}
    {-type:required}
    proc
} {
    Set the name of an APM Tcl procedure callback for a certain package version.
    Checks if the callback already exists and updates if it does.
    If version_id is not supplied the id of the currently enabled version
    of the package will be used.

    @see apm_supported_callback_types

    @author Peter Marklund
} {
    apm_assert_callback_type_supported $type

    if { $version_id eq "" } {
        if { $package_key eq "" } {
            error "apm_set_package_callback_proc: Invoked with both version_id and package_key empty. You must supply either of these"
        }

        set version_id [apm_version_id_from_package_key $package_key]
    }

    set current_proc [apm_get_callback_proc -type $type -version_id $version_id]

    if { $current_proc eq "" } {
        # We are adding
        db_dml insert_proc {}
    } else {
        # We are editing
        db_dml update_proc {}
    }
}

d_proc -public apm_get_callback_proc {
    {-type:required}
    {-package_key ""}
    {-version_id ""}
} {
    Return Tcl procedure name for the callback of a certain
    type for the given package. If no callback proc for the
    given type is present returns the empty string.

    @see apm_supported_callback_types

    @author Peter Marklund
} {
    apm_assert_callback_type_supported $type

    if { $version_id eq "" } {
        set version_id [apm_version_id_from_package_key $package_key]
    }
    return [db_string select_proc {} -default ""]
}

d_proc -public apm_remove_callback_proc {
    {-type:required}
    {-package_key:required}
} {
    Remove the callback of a certain type for the given package.

    @author Peter Marklund
} {
    apm_assert_callback_type_supported $type

    return [db_dml delete_proc {}]
}

d_proc -public apm_unused_callback_types {
    {-version_id:required}
} {
    Get a list enumerating the supported callback types
    that are not used by the given package version.
} {
    set used_callback_types [db_list used_callback_types {
        select distinct type
        from apm_package_callbacks
        where version_id = :version_id
    }]

    set supported_types [apm_supported_callback_types]

    set unused_types [list]
    foreach supported_type $supported_types {
        if {$supported_type ni $used_callback_types} {
            lappend unused_types $supported_type
        }
    }

    return $unused_types
}

d_proc -public apm_invoke_callback_proc {
    {-proc_name {}}
    {-version_id ""}
    {-package_key ""}
    {-arg_list {}}
    {-type:required}
} {
    Invoke the Tcl callback proc of a given type
    for a given package version. Any errors during
    invocation are logged.

    @param proc_name if this is provided it is called
    instead of attempting to look up the proc via the package_key or version_id
    (needed for before-install callbacks since the db is not populated when those
     are called).

    @return 1 if invocation
    was carried out successfully, 0 if no proc to invoke could
    be found. Will propagate any error thrown by the callback.

    @author Peter Marklund
} {
    array set arg_array $arg_list

    if {$proc_name eq ""} {
        set proc_name [apm_get_callback_proc \
                           -version_id $version_id \
                           -package_key $package_key \
                           -type $type]
    }

    if { $proc_name eq "" } {
        if {$type eq "after-instantiate"} {
            # We check for the old proc on format: package_key_post_instantiation package_id
            if { $package_key eq "" } {
                set package_key [apm_package_key_from_version_id $version_id]
            }
            set proc_name [apm_post_instantiation_tcl_proc_from_key $package_key]
            if { $proc_name eq "" } {
                # No callback and no old-style callback proc - no options left
                return 0
            }

            {*}$proc_name $arg_array(package_id)

            return 1

        } else {
            # No other callback procs to fall back on
            return 0
        }
    }

    # We have a nonempty name of a callback proc to invoke
    # Form the full command including arguments
    set command [list {*}$proc_name {*}[apm_callback_format_args -type $type -arg_list $arg_list]]

    # We are ready for invocation
    ns_log notice "apm_invoke_callback_proc: invoking callback $type with command <$command>"
    {*}$command

    return 1
}

ad_proc -public apm_assert_callback_type_supported { type } {
    Throw an error if the given callback type is not supported.

    @author Peter Marklund
} {
    if { ![apm_callback_type_supported_p $type]  } {
        error "The supplied callback type $type is not supported. Supported types are: [apm_supported_callback_types]"
    }
}

ad_proc -public apm_callback_type_supported_p { type } {
    Return 1 if the given type of callback is supported and 0
    otherwise.

    @author Peter Marklund
} {
    return [expr {$type in [apm_supported_callback_types]}]
}

d_proc -public apm_callback_format_args {
    {-version_id ""}
    {-package_key ""}
    {-type:required}
    {-arg_list {}}
} {
    Return a string on format -arg_name1 arg_value1 -arg_name2 arg_value2 ...
    for the callback proc of given type.

    @author Peter Marklund
} {
    array set args_array $arg_list

    set arg_string ""
    set provided_arg_names [array names args_array]
    foreach required_arg_name [apm_arg_names_for_callback_type -type $type] {
        if {$required_arg_name ni $provided_arg_names} {
            error "required argument $required_arg_name not supplied to callback proc of type $type"
        }

        append arg_string " -${required_arg_name} $args_array($required_arg_name)"
    }

    return $arg_string
}

d_proc -public apm_arg_names_for_callback_type {
    {-type:required}
} {
    Return the list of required argument names for the given callback type.

    @author Peter Marklund
} {
    array set arguments {
        after-instantiate {
            package_id
        }
        before-uninstantiate {
            package_id
        }
        before-unmount {
            package_id
            node_id
        }
        after-mount {
            package_id
            node_id
        }
        before-upgrade {
            from_version_name
            to_version_name
        }
        after-upgrade {
            from_version_name
            to_version_name
        }
    }

    if { [info exists arguments($type)] } {
        return $arguments($type)
    } else {
        return {}
    }
}

ad_proc -public apm_supported_callback_types {} {
    Gets the list of package callback types
    that are supported by the system.
    Each callback type represents a certain event or time
    when a Tcl procedure should be invoked, such as after-install

    @author Peter Marklund
} {
    return {
        before-install
        after-install
        before-upgrade
        after-upgrade
        before-uninstall
        after-instantiate
        before-uninstantiate
        after-mount
        before-unmount
    }
}

d_proc -public apm_callback_has_valid_args {
    {-type:required}
    {-proc_name:required}
} {
    Returns 1 if the specified callback proc of a certain
    type has a valid argument list in its definition and 0
    otherwise. Assumes that the callback proc is defined with
    ad_proc.

    @author Peter Marklund
} {

    if { [namespace which ::$proc_name] eq "" } {
        return 0
    }

    set test_arg_list ""
    set test_arg_list_spec ""
    foreach arg_name [apm_arg_names_for_callback_type -type $type] {
        lappend test_arg_list -$arg_name value
        lappend test_arg_list_spec -${arg_name}:required
    }

    if { $test_arg_list eq "" } {
        # The callback proc should take no args
        return [expr {[info args ::$proc_name] eq ""}]
    }

    if {[namespace which ::nsf::cmd::info] ne ""} {
        #
        # We can compare the signature of via nsf procs
        #
        return [expr {[::nsf::cmd::info parameter ::$proc_name] eq $test_arg_list_spec}]

    }

    # The callback proc should have required arg switches. Check
    # that the ad_proc arg parser doesn't throw an error with
    # test arg list
    if { [catch {
        set args $test_arg_list
        ::${proc_name}__arg_parser
    } errmsg] } {
        return 0
    } else {
        return 1
    }
}

d_proc -public apm_package_instance_new {
    {-package_key:required}
    {-instance_name ""}
    {-package_id ""}
    {-context_id ""}
} {

    Creates a new instance of a package and calls the post instantiation proc, if any. If the
    package is a singleton and already exists then this procedure will silently do nothing.

    @param package_key   The package_key of the package to instantiate.
    @param instance_name The name of the package instance, defaults to the pretty name of the
    package type.
    @param package_id    The id of the new package. Optional.
    @param context_id    The context_id of the new package. Optional.

    @return The id of the instantiated package
} {
    if { $instance_name eq "" } {
        set p_name [apm::package_version::attributes::get_instance_name $package_key]

        if {$p_name eq ""} {
            set instance_name [db_string pretty_name_from_key {select pretty_name
                from apm_enabled_package_versions
                where package_key = :package_key}]
        } else {
            set instance_name  "$p_name"
        }
    }
    #
    # Do not do anything for already instantiated singleton packages
    #
    if {![db_0or1row instantiated_singleton_p {
        select package_id
          from apm_package_types t,
               apm_packages p
         where t.singleton_p = 't'
           and t.package_key = p.package_key
           and t.package_key = :package_key}]
    } {
        #
        # Instantiate package
        #
        set package_id [db_exec_plsql invoke_new {}]

        apm_parameter_sync $package_key $package_id

        foreach inherited_package_key [nsv_get apm_package_inherit_order $package_key] {
            apm_invoke_callback_proc \
                -package_key $inherited_package_key \
                -type after-instantiate \
                -arg_list [list package_id $package_id]
        }
    }

    return $package_id
}

ad_proc apm_parameter_sync {package_key package_id} {

    Syncs the parameters in the database with the memory cache.  This must be called
    after creating a new package instance.

} {

    # Get all the parameter names and values for this package_id.
    set names_and_values [db_list_of_lists apm_parameter_names_and_values {
        select parameter_name, attr_value
        from apm_parameters p, apm_parameter_values v, apm_packages a
        where p.parameter_id = v.parameter_id
        and a.package_id = v.package_id
        and a.package_id = :package_id
    }]

    # Put it in the cache.
    foreach name_value_pair $names_and_values {
        ad_parameter_cache -set [lindex $name_value_pair 1] $package_id [lindex $name_value_pair 0]
    }
}

d_proc -public apm_package_instance_delete {
    package_id
} {
    Deletes an instance of a package
} {
    set package_key [apm_package_key_from_id $package_id]
    # ns_log notice "apm_package_instance_delete inherit order [nsv_get apm_package_inherit_order $package_key]"
    if {[nsv_exists apm_package_inherit_order $package_key]} {
        foreach inherited_package_key [nsv_get apm_package_inherit_order $package_key] {
            apm_invoke_callback_proc \
                -package_key $inherited_package_key \
                -type before-uninstantiate \
                -arg_list [list package_id $package_id]
        }
    }

    db_exec_plsql apm_package_instance_delete {}
}

d_proc -public apm_get_installed_versions {
    -array:required
} {
    Sets the current installed version of packages installed on this system
    in an array keyed by package_key.

    @param array Name of array in caller's namespace where you want this set
} {
    upvar 1 $array installed_version

    db_foreach installed_packages {
        select package_key, version_name
        from   apm_package_versions
        where  enabled_p = 't'
    } {
        set installed_version($package_key$version_name
    }
}

d_proc -public apm_get_installed_provides {
    -array:required
} {
    Sets the dependencies provided by the packages installed on this system
    in an array keyed by dependency service-uri.

    @param array Name of array in caller's namespace where you want this set
} {
    upvar 1 $array installed_provides

    # All packages provides themselves
    apm_get_installed_versions -array installed_provides

    # Now check what the provides clauses say
    db_foreach installed_provides {
        select service_uri,
        service_version
        from   apm_package_dependencies d,
        apm_package_versions v
        where  d.dependency_type = 'provides'
        and    d.version_id = v.version_id
        and    v.enabled_p = 't'
    } {
        if { ![info exists installed_provides($service_uri)]
             || [apm_version_names_compare $installed_provides($service_uri) $service_version] == -1
         } {
            set installed_provides($service_uri$service_version
        }
    }
}


##
## Logging
##

d_proc -public apm_log {
    level
    msg
} {
    Centralized APM logging. If you want to debug the APM, change
    APMDebug to Debug and restart the server.
} {
    if {"APMDebug" ne $level } {
        ns_log $level $msg
    }
}

ad_proc -public apm_application_new_checkbox {} {
    Return an HTML checkbox of package_key and package names
    for applications that can be mounted in the site-map. Excludes
    singletons that are already instantiated.

    @author Peter Marklund
} {
    set options [list]
    db_foreach package_types {
         select package_key, pretty_name
         from apm_package_types t
         where not (singleton_p = 't'
                    and exists (select 1 from apm_packages
                                where package_key = t.package_key))
         order by pretty_name
    } {
        lappend options [subst {<option value="$package_key">$pretty_name</option>}]
    }

    # If this is a site-wide admin, offer a link to the package manager
    if { [acs_user::site_wide_admin_p] } {
        lappend options {<option value="/new">--Install new package--</option>}
    }

    return [subst {<select name="package_key">[join $options]</select>}]
}

ad_proc -private apm::read_files {path file_list} {
    Read the contents from a list of files at a certain path. Return
    the data to the caller as a big string.
} {
    set data ""
    foreach file $file_list {
        if {![catch {set fp [open ${path}/${file} r]} err]} {
            append data [read $fp]
            close $fp
        }
    }
    return $data
}

d_proc -public apm::metrics {
    -package_key:required
    -file_type:required
    -array
} {
    Return some code metrics about the files in package $package_key. This
    will return an array or dict containing at least the following items:
    <ul>
    <li>count - the number of files</li>
    <li>lines - the number of lines in the files</li>
    <li>blank_lines - the number of blank lines in the files</li>
    <li>comment_lines - the number of blank lines in the files</li>
    <li>procs - the number of procs, if applicable (0 if not applicable)</li>
    </ul>
    <p>
    Valid file_type's:
    <ul>
    <li>data_model_pg - PG datamodel files</li>
    <li>data_model_ora - Oracle datamodel files</li>
    <li>include_page - ADP files in package_key/lib</li>
    <li>content_page - ADP files in package_key/www</li>
    <li>tcl_procs - Tcl procs in package_key/tcl</li>
    <li>test_procs - automated tests in package_key/tcl/test</li>
    <li>documentation - docs in package_key/www/doc</li>
    </ul>
    When the array is provided, it will be used for setting the result.
    Otherwise a dict with the metrics information is returned.

    This proc is cached.

    @author Vinod Kurup
    @creation-date 2006-02-09

    @param package_key The package_key of interest
    @param file_type See options above
    @param array variable to hold the array that will be returned
} {
    set data [util_memoize [list apm::metrics_internal $package_key $file_type]]
    if {[info exists array]} {
        upvar $array metrics
        array set metrics $data
    }
    return $data
}

d_proc -private apm::metrics_internal {
    package_key
    file_type
} {
    The cached version of apm::metrics

    @see apm::metrics
} {
    array set metrics {}
    set package_path [acs_package_root_dir $package_key]

    # We'll be using apm_get_package_files to get a list of files
    # by file type.

    switch -- $file_type {
        data_model_pg -
        data_model_ora {
            set file_types [list data_model_create data_model]
        }
        default {
            set file_types $file_type
        }
    }

    set filelist [apm_get_package_files \
                      -include_data_model_files \
                      -all_db_types \
                      -package_key $package_key \
                      -file_types $file_types]

    # filelist needs to be weeded for certain file types
    switch -- $file_type {
        include_page -
        content_page {
            # weed out non-.adp files
            set adp_files {}
            foreach file $filelist {
                if { [string match {*.adp} $file] } {
                    lappend adp_files $file
                }
            }
            set filelist $adp_files
        }
        data_model_pg {
            # ignore drop and upgrade scripts
            set pg_files {}
            foreach file $filelist {
                if { [string match {*/postgresql/*} $file]
                     && ![string match "*-drop.sql" $file]
                     && ![string match {*/upgrade/*} $file]
                 } {
                    lappend pg_files $file
                }
            }
            set filelist $pg_files
        }
        data_model_ora {
            # ignore drop and upgrade scripts
            set ora_files {}
            foreach file $filelist {
                if { [string match {*/oracle/*} $file]
                     && ![string match "*-drop.sql" $file]
                     && ![string match {*/upgrade/*} $file]
                 } {
                    lappend ora_files $file
                }
            }
            set filelist $ora_files
        }
    }

    # read the files, so we can count lines and grep for procs
    set filedata [apm::read_files $package_path $filelist]

    # The first metrics are easy and generic
    set metrics(count) [llength $filelist]
    set lines [split $filedata \n]
    set metrics(lines) [llength $lines]

    set metrics(blank_lines) [regexp -all -line {^\s*$} $filedata]

    #
    # Count comment lines. We check here the comments available to
    # proc_doc and add these to the line comments below.
    #
    set metrics(comment_lines) 0

    foreach file $filelist {
        if {[nsv_exists api_proc_doc_scripts packages/$package_key/$file]} {
            #
            # Add for every found entry in proc_doc the contents
            # obtained from the doc argument of ad_proc.
            #
            foreach p [nsv_get api_proc_doc_scripts packages/$package_key/$file] {
                set proc_doc [nsv_get api_proc_doc $p]
                set main_doc 0
                if {[dict exists $proc_doc main]} {
                    incr main_doc [llength [split [dict get $proc_doc main] \n]]
                }
                set return_doc 0
                if {[dict exists $proc_doc return]} {
                    incr return_doc [llength [split [dict get $proc_doc return] \n]]
                }
                incr metrics(comment_lines) $main_doc
                incr metrics(comment_lines) $return_doc
                #ns_log notice "$file: $p [nsv_exists api_proc_doc $p] main $main_doc return doc $return_doc"
            }
        }
    }

    #
    # Extract procs, depending on the file_type
    #
    switch -exact $file_type {
        tcl_procs {
            set metrics(procs) [regexp -all -line {^\s*ad_proc} $filedata]
            set metrics(comment_lines) [regexp -all -line {^\s*#} $filedata]
        }
        test_procs {
            set metrics(procs) [regexp -all -line {^\s*aa_register_case} $filedata]
            set metrics(comment_lines) [regexp -all -line {^\s*#} $filedata]
        }
        data_model_pg {
            set metrics(procs) [regexp -all -line -nocase {^\s*create\s+or\s+replace\s+function\s+} $filedata]
            set metrics(comment_lines) [regexp -all -line {^\s*--} $filedata]
        }
        data_model_ora {
            set metrics(procs) [expr {[regexp -all -line -nocase {^\s+function\s+} $filedata] +
                                      [regexp -all -line -nocase {^\s+procedure\s+} $filedata]}]
            set metrics(comment_lines) [regexp -all -line {^\s*--} $filedata]
        }
        default {
            # other file-types don't have procs
            set metrics(procs) 0
        }
    }

    return [array get metrics]
}

d_proc -public apm::get_package_descendent_options {
    package_key
} {
    Get a list of pretty name, package key pairs for all packages which are descendents
    of the given package key.

    @param package_key The parent package's key.
    @return a list of pretty name, package key pairs suitable for use in a template
    select widget.
} {
    set in_clause '[join [::apm_package_descendents $package_key] ',']'
    return [db_list_of_lists get {}]
}


d_proc -public apm::convert_type {
    -package_id:required
    -old_package_key:required
    -new_package_key:required
} {
    Convert a package instance to a new type, doing the proper instantiate and mount callbacks and
    parameter creation.

    @param package_id The package instance to convert.
    @param old_package_key The package key we're converting from.
    @param new_package_key The new subsite type we're converting to.

} {
    db_dml update_package_key {}
    util_memoize_flush "apm_package_key_from_id_not_cached $package_id"

    set node_id [site_node::get_node_id_from_object_id -object_id $package_id]
    if { $node_id ne "" } {
        site_node::update_cache -node_id $node_id
    }

    # DRB: parameter fix!
    db_foreach get_params {} {
        db_1row get_new_parameter_id {}
        db_dml update_param {}
    }
    db_list copy_new_params {}
    apm_parameter_sync $new_package_key $package_id

    foreach inherited_package_key [::apm_package_inherit_order $new_package_key] {
        if {$inherited_package_key ni [::apm_package_inherit_order $old_package_key]} {
            apm_invoke_callback_proc \
                -package_key $inherited_package_key \
                -type after-instantiate \
                -arg_list [list package_id $package_id]
            if { $node_id ne "" } {
                apm_invoke_callback_proc \
                    -package_key $inherited_package_key \
                    -type after-mount \
                    -arg_list [list node_id $node_id package_id $package_id]
            }
        }
    }

}


#
### Deprecated procs
#

# apisano 2018-05-14: there is a thread cache for this now, no need
# IMO to maintain a datamodel to know which databases we
# support. Original code is the commented one.
ad_proc -deprecated -private apm_pretty_name_for_db_type { db_type } {

    Returns the pretty name corresponding to a particular file type key
    (memoizing to save a database hit here and there).

} {
    set pos [lsearch -index 0 -exact $::acs::known_database_types $db_type]
    return [lindex $::acs::known_database_types $pos 2]
    # return [util_memoize [list db_string pretty_db_name_select "
    #     select pretty_db_name
    #     from apm_package_db_types
    #     where db_type_key = :db_type
    # " -default "all" -bind [list db_type $db_type]]]
}

#
# Local variables:
#    mode: tcl
#    tcl-indent-level: 4
#    indent-tabs-mode: nil
# End: