3.3. The GLOBALS Object

Every ReportServer script is initialized with a scope that contains an object called GLOBALS. This object exposes ReportServer functionality to your script. This allows you to access ReportServer services but it also provides certain functionality to scripts such as easily accessing files in the fileserver. The most common case is access of ReportServer services and to access entities.

Tip: The GLOBALS object is of type net.datenwerke.rs.scripting.service.scripting.scriptservices.GlobalsWrapper. The javadoc documentation provides an overview of the methods provided by GLOBALS: https://reportserver.net/api/latest/javadoc/net/datenwerke/rs/scripting/service/scripting/scriptservices/GlobalsWrapper.html.

Services can be retrieved via the method getInstance(). getInstance takes a class object as input and returns the corresponding service object. It is also possible to get access to a Provider object for a service. Providers can be regarded as containers which do not immediately access the service but which allow access to that particular service. This can for example be helpful when writing complex scripts and you want to give access to services to functions or classes. Providers can be accessed via the getProvider method which also takes a class object as input.

In the following we create a simple script that allows to search your ReportServer installation for users. For this we will use the SearchService located in package net.datenwerke.rs.search.service.search. The service exposes the search functionality provided by ReportServer.

Tip: In order to use auto completion and automatic import statements when editing scripts in Eclipse you must add all projects to the list of required projects. For this open the groovy project's properties (right-click on the project then choose properties) and Java Build Path. Choose the Projects tab and select all other projects.
Tip: Eclipse's auto-completion works better if you program Groovy using explicit types. That is, instead of writing
def var = 'string'
use
String var = 'string'

Create a new script in Eclipse called searchuser.groovy. We will require the SearchService from the GLOBALS object. We will then use the locate method to retrieve a list of results. As input we will simply pass on the argument array (converted to a string).

package myscripts

import net.datenwerke.rs.search.service.search.SearchService
import net.datenwerke.security.service.usermanager.entities.User

SearchService searchSvc = GLOBALS.getInstance(SearchService)
searchSvc.locate(User.class, args.join(" "))

If we add this script to our tmp folder in ReportServer and execute it via

exec searchuser.groovy root

you will get the output

[root root]

Let us create a second user via the user manager called "Tom Rootinger". If we run our script again with root as argument we will get the same output. This is because, by default the search service looks for exact matches. If we run the script as

exec searchuser.groovy root*

we get the expected result:

[root root, Tom Rootinger]

In a next step we want to use the HistoryService (located in net.datenwerke.gf.service.history) to generate links for the objects found by our script. The HistoryService has a single method that takes an object and returns a list of links (objects of type HistoryLink). We will simply take the first link in this list (if it exists) and output it. The adapted script looks like

package myscripts

import net.datenwerke.gf.service.history.HistoryService
import net.datenwerke.rs.search.service.search.SearchService
import net.datenwerke.security.service.usermanager.entities.User

SearchService searchSvc = GLOBALS.getInstance(SearchService)
HistoryService historySvc = GLOBALS.getInstance(HistoryService)

searchSvc.locate(User.class, args.join(" ")).collect{ 
	historySvc.buildLinksFor(it).get(0)?.getLink()
}.join("\n")

If we run this again using exec searchuser.groovy root* we get as output

usermgr/path:1.2.3&nonce:-1668828071
usermgr/path:1.4&nonce:475784900

On the one hand we are missing the server address and on the other, wouldn't it be nice to be able to actually click on the link? The server address can be accessed via the ReportServerService. Thus we could adapt our script as

package myscripts

import net.datenwerke.gf.service.history.HistoryService
import net.datenwerke.rs.core.service.reportserver.ReportServerService
import net.datenwerke.rs.search.service.search.SearchService
import net.datenwerke.rs.terminal.service.terminal.obj.CommandResult
import net.datenwerke.security.service.usermanager.entities.User

SearchService searchSvc = GLOBALS.getInstance(SearchService)
HistoryService historySvc = GLOBALS.getInstance(HistoryService)
String urlBase = GLOBALS.getInstance(ReportServerService).serverInfo.baseURL

searchSvc.locate(User.class, args.join(" ")).collect{ 
	  urlBase + historySvc.buildLinksFor(it).get(0)?.link
}

For the second part we need to return an object of type CommandResult (in package net.datenwerke.rs.terminal.service.terminal.obj). The CommandResult object allows us to better specify how the terminal treats the result returned by the script. It is able to display lists, tables, html and what we need for our task: links. The CommandResult object can create links either to external pages via addResultHyperLink() method or to internal locations via the addResultAnchor() method. Following is the final script.

package myscripts

import net.datenwerke.gf.service.history.HistoryService
import net.datenwerke.rs.core.service.reportserver.ReportServerService
import net.datenwerke.rs.search.service.search.SearchService
import net.datenwerke.rs.terminal.service.terminal.obj.CommandResult
import net.datenwerke.security.service.usermanager.entities.User

SearchService searchSvc = GLOBALS.getInstance(SearchService)
HistoryService historySvc = GLOBALS.getInstance(HistoryService)
String urlBase = GLOBALS.getInstance(ReportServerService).serverInfo.baseURL

CommandResult result = new CommandResult()
def links = searchSvc.locate(User.class, args.join(" ")).collect{ 
	  result.addResultHyperLink(it.getName(), historySvc.buildLinksFor(it).get(0)?.link )
}

return result
Tip: Via the terminal/alias.cf configuration file you can make scripts directly accessible. For example the entry
<entry>
	<alias>search</alias>
	<command>exec /fileserver/bin/tmp/searchuser.groovy</command>
</entry>
would allow you to access your searchuser script from anywhere using the command search. If you change the config file don't forget to make ReportServer reload the configuration using the config reload terminal command.