Class EssServerImpl

java.lang.Object
com.appliedolap.essbase.AbstractEssObject
com.appliedolap.essbase.impl.EssServerImpl
All Implemented Interfaces:
EssObject, EssServer

public class EssServerImpl extends AbstractEssObject implements EssServer
Server connection. This object is the general starting point for working with the Essbase REST API client library. See the main constructor EssServerImpl(String, String, String) for information on instantiating.
  • Constructor Details

    • EssServerImpl

      public EssServerImpl(String server, String username, String password)
      Creates a new server connection object. At present, the server path is assumed to be in the exact format such as: .... In other words, this class will currently not try to prepend or append any information such as the protocol, port, or REST path. Note that if using HTTPS without a valid cert, you may encounter PKIX errors. Note: SSL verification is currently turned off.
      Parameters:
      server - the server REST API path
      username - the username
      password - the password
    • EssServerImpl

      public EssServerImpl(String server, EssAuthentication authentication)
      Connects using the given authentication strategy, which need not be a username and password - see EssAuthentication. The way in for a session established elsewhere, such as by a user signing in through an external identity provider.
      Parameters:
      server - the server REST API path
      authentication - how to authenticate
    • EssServerImpl

      public EssServerImpl(EssServerConnectionDetailsImpl connectionDetails)
  • Method Details

    • getApiSpec

      public EssApiSpec getApiSpec()
      Description copied from interface: EssServer
      The server's own OpenAPI/Swagger definition of its REST API.

      Where it lives depends on the release, which is the reason this exists rather than callers building the URL themselves: 21.7 serves a Swagger 2.0 document at /rest/v1/swagger.json and answers 404 for openapi.json, while 26.1 serves an OpenAPI 3.0.1 document at /rest/v1/openapi.json and answers 404 for swagger.json. Asking for the wrong one is not a soft failure - it is a 404 - so the candidates are tried in turn.

      Specified by:
      getApiSpec in interface EssServer
    • getInstanceDetails

      public Map<String,Object> getInstanceDetails()
      Description copied from interface: EssServer
      Everything the server reports about this deployment, exactly as it reports it.

      Deliberately untyped, unlike EssServer.getAboutInstance(). This endpoint is a bag of capability flags describing one deployment, and which flags exist varies by version: 21.7 answers with idcs and provisioningSupported, while 26.1 answers with ten fields including a split of that one into service- and application-role provisioning, several AI feature flags, and a logout URL. A generated model pins the field names at whatever the spec said when it was generated and silently discards the rest, so against a newer server the typed view goes empty precisely when the server has more to say. A map cannot go out of date that way.

      Values are left as the server sent them - booleans stay booleans - so a caller can test a flag as well as display it. idcs is the interesting one: it says the deployment authenticates through Oracle's identity service, which is what makes a username and password useless for a federated user.

      Specified by:
      getInstanceDetails in interface EssServer
      Returns:
      the fields the server returned, in the order it returned them
    • getAboutDetails

      public Map<String,Object> getAboutDetails()
      Description copied from interface: EssServer
      Everything the server reports about the product, exactly as it reports it.

      Untyped for the same reason EssServer.getInstanceDetails() is: EssServer.getAbout() names four fields fixed at whatever the spec said when the client was generated, and a 26.1 server answers with five - it adds listingVersion, which a typed view drops on the floor without saying so. The fields here are whatever came back.

      Specified by:
      getAboutDetails in interface EssServer
      Returns:
      the fields the server returned, in the order it returned them
    • getAuthentication

      public EssAuthentication getAuthentication()
      Description copied from interface: EssServer
      How this connection authenticates, so that code outside the generated client can present the same identity - a download bypass, or a local proxy standing in front of the server's own web pages.

      Returns the live strategy rather than a snapshot: ask it for headers at the moment of the request, because a session-based strategy's answer changes once a session is established, and again once it is signed off.

      Specified by:
      getAuthentication in interface EssServer
    • signOff

      public void signOff()
      Description copied from interface: EssServer
      Ends this client's own session on the server.

      Distinct from EssServer.killSessions(boolean), which ends other people's. This is signing off: the session this client established stops being valid, and the server stops holding it.

      What happens next depends on how this connection authenticates. With a username and password, the next call simply authenticates again and gets a fresh session. With a session supplied from outside - a federated sign-in, say - there is nothing to fall back to and subsequent calls will be rejected, which is precisely what signing off means in that case.

      Specified by:
      signOff in interface EssServer
    • getSessionExpiry

      public Optional<Instant> getSessionExpiry()
      Description copied from interface: EssServer
      When this client's session expires, if the server has said. Empty when there is no session, or when the session was supplied from outside rather than established here - the expiry is reported alongside the session, so only the client that established it hears about it.
      Specified by:
      getSessionExpiry in interface EssServer
    • getName

      public String getName()
      Description copied from interface: EssObject
      Gets the name of this object. This will generally be the "nice" and "unique" name of this object, such as the application name, cube, member, variable, or whatever.
      Specified by:
      getName in interface EssObject
      Specified by:
      getName in interface EssServer
      Returns:
      the simple name of this object
    • getType

      public EssObject.Type getType()
      Description copied from interface: EssObject
      Gets the type of this object.
      Specified by:
      getType in interface EssObject
      Specified by:
      getType in interface EssServer
      Returns:
      the object type
    • getApplications

      public List<EssApplication> getApplications()
      Description copied from interface: EssServer
      Fetch the list of applications available on the server for the currently connected user. The number of returned applications is limited to 1000 (the value of EssServer.MAX_APPLICATIONS).
      Specified by:
      getApplications in interface EssServer
      Returns:
      a list of applications
    • getApplication

      public EssApplicationImpl getApplication(String applicationName)
      Description copied from interface: EssServer
      Gets an application with the given name
      Specified by:
      getApplication in interface EssServer
      Parameters:
      applicationName - the application name
      Returns:
      an application object for the application
    • getFiles

      public List<EssFile> getFiles()
      Description copied from interface: EssServer
      Gets the list of files available through the files API. The returned files may include folders.
      Specified by:
      getFiles in interface EssServer
      Returns:
      the list of files on this server
    • getFile

      public EssFile getFile(String path, String filename)
      Finds a file by the folder holding it and its name.

      Lists through EssFolderImpl, which is the one listing path that encodes a path correctly - the generated filesListFiles escapes the separators, so anything below the top level came back as "Specified path '/%2Fapplications%2FSample' does not exist". A leading slash is fine here: catalogue paths are reported with one and the encoder trims it.

      Specified by:
      getFile in interface EssServer
      Parameters:
      path - the path to the file, such as gallery/Applications/Demo Samples/Block Storage
      filename - the name of the file, such as Sample_Basic.xlsx
      Returns:
      the file if it exists, null otherwise
    • getSessions

      public List<EssSession> getSessions()
      Specified by:
      getSessions in interface EssServer
    • killSessions

      public void killSessions(boolean logoff)
      Description copied from interface: EssServer
      Kill all sessions on the server.
      Specified by:
      killSessions in interface EssServer
      Parameters:
      logoff - true to also log them off
    • killSessions

      public void killSessions(String userId, boolean logoff)
      Description copied from interface: EssServer
      Kill all sessions on the server for the given user.
      Specified by:
      killSessions in interface EssServer
      Parameters:
      userId - the user ID
      logoff - true to also log them off
    • getHomePath

      public EssFolder getHomePath()
      Description copied from interface: EssServer
      Gets the home path of the currently connected user. The value of the home path is returned by a REST API call (curiously, one that returns plaintext instead of JSON but whatever). The value is ostensibly /users/ followed by the name of the connected user (e.g. /users/admin).
      Specified by:
      getHomePath in interface EssServer
      Returns:
      a folder object for the user's home path
    • getSharedPath

      public EssFolder getSharedPath()
      Description copied from interface: EssServer
      The shared folder every user can see, /shared.

      The counterpart to EssServer.getHomePath(), which was here without it.

      Specified by:
      getSharedPath in interface EssServer
      Returns:
      the shared folder
    • getUtilities

      public List<EssUtility> getUtilities()
      Description copied from interface: EssServer
      Gets the list of utilities on this server.
      Specified by:
      getUtilities in interface EssServer
      Returns:
      the server utilities
    • getJobs

      public List<EssJob> getJobs()
      Description copied from interface: EssServer
      Gets the list of jobs on this server.
      Specified by:
      getJobs in interface EssServer
      Returns:
      the list of jobs
    • getPermissions

      public List<EssPermission> getPermissions()
      Description copied from interface: EssServer
      Who holds which service-level role - Service Administrator, Power User, User.

      Unlike EssServer.getUsers() and EssServer.getGroups(), this answers on a deployment behind an external identity provider: the directory lives there, but the role assignments are Essbase's own. It is the one way to see who can do what on such a server.

      Specified by:
      getPermissions in interface EssServer
      Returns:
      the service role assignments
    • getUsers

      public List<EssUser> getUsers()
      Description copied from interface: EssServer
      The users this server holds.

      Only meaningful where Essbase owns its own security. A deployment behind an external identity provider - idcs in EssServer.getInstanceDetails() - keeps its users in the provider and answers HTTP 400 "This operation is not supported. Contact administrator" here, the same as it does for EssServer.getGroups(). Check the flag before asking, rather than treating the refusal as a failure.

      Specified by:
      getUsers in interface EssServer
      Returns:
      the users, where the server has any to report
    • getGroups

      public List<EssGroup> getGroups()
      Description copied from interface: EssServer
      Gets a list of groups on this server
      Specified by:
      getGroups in interface EssServer
      Returns:
      the list of groups
    • createGroup

      public EssGroup createGroup(String name, String description, String role)
      Description copied from interface: EssServer
      Creates a group.

      Only on a server that owns its own security; a deployment behind an external identity provider keeps its groups in the provider and refuses this, the same as it refuses EssServer.getGroups().

      Specified by:
      createGroup in interface EssServer
      Parameters:
      name - the group name, which is also its id
      description - what the group is for, or null
      role - the service-level role it grants its members - User, Power User or Service Administrator. Required: the server rejects a group without one.
      Returns:
      the group as the server created it
    • getGroup

      public EssGroup getGroup(String name)
      Description copied from interface: EssServer
      One group by name.
      Specified by:
      getGroup in interface EssServer
      Parameters:
      name - the group name
      Returns:
      the group
    • getVariables

      public List<EssServerVariable> getVariables()
      Description copied from interface: EssServer
      Gets server-scoped variables.
      Specified by:
      getVariables in interface EssServer
      Returns:
      the server-wide variables
    • createVariable

      public EssServerVariable createVariable(String name, String value)
      Description copied from interface: EssServer
      Creates a new server-wide variable with the given name and value.
      Specified by:
      createVariable in interface EssServer
      Parameters:
      name - the name of the variable
      value - the value of the variable
    • getAbout

      public EssServerImpl.About getAbout()
      Description copied from interface: EssServer
      Gets the "about" information for this server.
      Specified by:
      getAbout in interface EssServer
      Returns:
      the server about info
    • getAboutInstance

      public EssServerImpl.AboutInstance getAboutInstance()
      Specified by:
      getAboutInstance in interface EssServer
    • createApplication

      public void createApplication(String applicationName, String databaseName)
      Description copied from interface: EssServer
      Creates an application (and a database) with the given names. While we tend to historically think of Essbase as employing the concept of an application containing one or more databases/cubes, most of the operations in the REST API are centered around actions you do on a particular cube, and in cases like these where you are creating a cube, there is no separate application creation step, it just gets created or re-used as the case may be.

      The default database creation options will be BSO cube with scenarios and duplicates turned off. For more granular control of the created database type, use EssServer.createApplication(String, String, EssServerImpl.DatabaseCreateOptions).

      Specified by:
      createApplication in interface EssServer
      Parameters:
      applicationName - the application name
      databaseName - the database name
    • createApplication

      public void createApplication(String applicationName, String databaseName, EssServerImpl.DatabaseCreateOptions databaseCreateOptions)
      Description copied from interface: EssServer
      Create an application/database with the given name and options.
      Specified by:
      createApplication in interface EssServer
      Parameters:
      applicationName - the name of the application
      databaseName - the name of the database/cube
      databaseCreateOptions - the database creation options
    • createApplicationFromWorkbook

      public EssJob createApplicationFromWorkbook(String application, String database, EssFile file)
      Description copied from interface: EssServer
      Creates or updates an application from an uploaded workbook.
      Specified by:
      createApplicationFromWorkbook in interface EssServer
      Parameters:
      application - the application
      database - the cube/database
      file - the XLSX file
      Returns:
      a new job for the creation process
    • createApplicationFromWorkbook

      public EssJob createApplicationFromWorkbook(String application, String database, EssFile file, EssWorkbookImportOptions options)

      Every flag is sent as the string "true" or "false" rather than a JSON boolean, which is not a style choice - the parameters bean types them as strings and the server rejects real booleans here. The job echoes back the four it acted on, which is the only way to confirm it read them.

      Specified by:
      createApplicationFromWorkbook in interface EssServer
      Parameters:
      application - the application to build
      database - the cube within it
      file - the workbook, in the server's catalogue
      options - what the import should do
      Returns:
      the submitted job, which runs in the background
    • getURLs

      public List<EssURL> getURLs()
      Description copied from interface: EssServer
      Returns the list of URLs known to this server. Generally speaking this seems to be the URL for the Jet UI, REST API, XMLA provider, and some others.
      Specified by:
      getURLs in interface EssServer
      Returns:
      list of URLs from the corresponding API
    • getDataSources

      public List<EssDataSource> getDataSources()
      Specified by:
      getDataSources in interface EssServer
    • getDataSource

      public EssDataSource getDataSource(String dataSourceName)
      Description copied from interface: EssServer
      Get the data source with the given name. Will throw NoSuchEssbaseObjectException if there is no data source with that name.
      Specified by:
      getDataSource in interface EssServer
      Parameters:
      dataSourceName - the data source name
      Returns:
      the data source with that name
    • streamDataSource

      public void streamDataSource(String query, boolean includeHeaders, String delimiter, Map<String,Object> params, OutputStream outputStream)
      Runs a query against a data source and writes the rows out.

      Two calls, and both are load-bearing. POST /datasources/query does not return data - it answers with the column list and a link carrying a stream id, and the rows come from a follow-up GET on that link.

      The stream lives in server-side session state, so the second call has to reach the same session as the first. Under an authentication strategy that establishes no session - Basic, for one - every request lands somewhere new and the follow-up answers Stream id '...' does not exist. The cookies the first response set are therefore carried onto the second explicitly, which works whatever the strategy is. Oracle's own curl example hints at this with a --cookie-jar that is easy to read as boilerplate.

      Not /datasources/query/stream, which also exists, and which answers HTTP 200 with Failed to stream... Failed to execute query. in the body for every input tried.

      Specified by:
      streamDataSource in interface EssServer
      Parameters:
      query - the query
      includeHeaders - whether to include headers in the result
      delimiter - the delimiter (currently only space and tab are supported by the server, you can use constants in EssDataSourceImpl for convenience)
      params - the parameters, if any. If none, supply an empty map
      outputStream - the output stream to write results to
    • deleteDataSource

      public void deleteDataSource(String name)
      Description copied from interface: EssServer
      Removes a global data source.
      Specified by:
      deleteDataSource in interface EssServer
      Parameters:
      name - the data source name
    • getConnections

      public List<EssConnection> getConnections()
      Description copied from interface: EssServer
      The global connections defined on this server.
      Specified by:
      getConnections in interface EssServer
      Returns:
      the connections
    • getConnection

      public Optional<EssConnection> getConnection(String name)
      One connection, with everything the server knows about it.

      Two calls, because neither endpoint answers with the whole object: the list carries description but no path, and fetching one carries path but no description. A caller shouldn't have to know that, so they are merged here.

      Specified by:
      getConnection in interface EssServer
      Parameters:
      name - the connection name
      Returns:
      the connection, or empty if there is none
    • createFileConnection

      public EssConnection createFileConnection(String name, String catalogPath, String description)
      Description copied from interface: EssServer
      Creates a connection to a file in the Essbase catalogue.

      The path names a file, not the folder holding it - a file connection stands for one file, and the data source built on it carries no filename of its own.

      Specified by:
      createFileConnection in interface EssServer
      Parameters:
      name - the connection name
      catalogPath - the file, e.g. /gallery/Technical/Filters/UserDetails.csv
      description - optional description
      Returns:
      the connection as created
    • testFileConnection

      public Optional<String> testFileConnection(String name, String catalogPath)
      Description copied from interface: EssServer
      Tests a connection that hasn't been saved, so a caller can check before committing.
      Specified by:
      testFileConnection in interface EssServer
      Parameters:
      name - the connection name to test under
      catalogPath - the file to point at
      Returns:
      empty when it connects, otherwise the server's reason
    • getServerLogTypes

      public List<String> getServerLogTypes()
      The about information of this server.
      Specified by:
      getServerLogTypes in interface EssServer
      Returns:
      the server log types, empty if this deployment serves none
    • downloadLatestServerLog

      public void downloadLatestServerLog(String serverType, OutputStream outputStream)
      Description copied from interface: EssServer
      Writes the latest server log of the given type to the stream.
      Specified by:
      downloadLatestServerLog in interface EssServer
      Parameters:
      serverType - one of EssServer.getServerLogTypes()
      outputStream - where to write it
    • downloadServerLogsAsZip

      public void downloadServerLogsAsZip(String serverType, OutputStream outputStream)
      Description copied from interface: EssServer
      Writes every server log of the given type, as a zip, to the stream.
      Specified by:
      downloadServerLogsAsZip in interface EssServer
      Parameters:
      serverType - one of EssServer.getServerLogTypes()
      outputStream - where to write it
    • getMdxFunctions

      public List<EssMdxFunctionGroup> getMdxFunctions()
      Description copied from interface: EssServer
      The MDX functions this server understands, in the server's own groups.

      A property of the server's MDX dialect, not of any cube - the same server answers byte-for-byte identically whichever cube is asked. There is no server-level endpoint for it though, so this finds a cube and asks through that; a stopped application will do, since the answer does not depend on the data.

      Specified by:
      getMdxFunctions in interface EssServer
      Returns:
      the function groups, in the order the server listed them
    • getMcp

      public EssMcp getMcp()
      Description copied from interface: EssServer
      The MCP server built into this Essbase, if it has one.

      Points the opposite way from EssCube.getAi(): this is Essbase offering itself as a tool provider to somebody else's model, rather than Essbase calling out to one. A server can have this working while every /ai endpoint is unconfigured, and usually does.

      Specified by:
      getMcp in interface EssServer
      Returns:
      the MCP server, which answers isAvailable() false on anything before 26.1
    • getAi

      public EssServerAi getAi()
      Description copied from interface: EssServer
      This server's own generative-AI setup: whether it supports AI, whether it is switched on, which capabilities are on, and whether any GenAI connection has been configured.

      The server-level answer to a question EssCube.getAi() can only answer per cube. The cube walks the whole setup chain, so asking it "is AI configured here" costs one walk per cube and mixes the server's answer in with each application's. This is the half that is the same for every cube on the server, asked once.

      Specified by:
      getAi in interface EssServer
      Returns:
      the server's AI setup, never null; nothing is contacted until it is asked something
    • getMaintenanceLimits

      public EssMaintenanceLimits getMaintenanceLimits()
      Description copied from interface: EssServer
      What the server reports about the machine it runs on - free disk and memory, and any configured ceilings. The only window the REST API offers onto the host.
      Specified by:
      getMaintenanceLimits in interface EssServer
      Returns:
      the limits
    • getLogSettings

      public List<EssLogSetting> getLogSettings()
      Description copied from interface: EssServer
      How each ODL log handler rotates.

      Worth having beside the logs themselves: a handler holding ten megabytes per file and five hundred in total has silently discarded everything older, and nothing in the log says so.

      Specified by:
      getLogSettings in interface EssServer
      Returns:
      one entry per handler
    • setLogSettings

      public void setLogSettings(List<EssLogSetting> settings)
      Description copied from interface: EssServer
      Changes how the log handlers rotate.

      Send every handler, not only the changed one - this replaces the set. Start from EssServer.getLogSettings() and use EssLogSetting.withSizes(java.lang.Integer, java.lang.Integer) on the one being altered.

      Specified by:
      setLogSettings in interface EssServer
      Parameters:
      settings - the full set of handlers
    • getUploadConfig

      public EssUploadConfig getUploadConfig()
      Description copied from interface: EssServer
      How this server wants large files uploaded - the part size, and how many parts it allows.

      Rarely needed directly: EssFolder.uploadFile(java.io.File) already reads this and sends a file whichever way the server asks for. Worth having for anything that wants to say in advance what an upload is going to involve.

      Specified by:
      getUploadConfig in interface EssServer
      Returns:
      the upload configuration