Skip to content

Commit f0801fe

Browse files
committed
documentation of the available interface.
multiple script upload is supported in multi threading. preparing release 2.1.4
1 parent d2445b8 commit f0801fe

6 files changed

Lines changed: 692 additions & 22 deletions

File tree

README.md

Lines changed: 161 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,14 @@ The library is published to Maven Central under the coordinates `com.microfocus.
2525
<dependency>
2626
<groupId>com.microfocus.adm.performancecenter</groupId>
2727
<artifactId>plugins-common</artifactId>
28-
<version>1.2.3</version>
28+
<version>1.2.4</version>
2929
</dependency>
3030
```
3131

3232
### Gradle dependency
3333

3434
```groovy
35-
implementation 'com.microfocus.adm.performancecenter:plugins-common:1.2.3'
35+
implementation 'com.microfocus.adm.performancecenter:plugins-common:1.2.4'
3636
```
3737

3838
## Main client interface
@@ -79,6 +79,165 @@ The main API contract is `PcRestProxyClient` in:
7979
- `extractTestIdFromString(...)`, `readYaml(...)`, `GetPcServer()`, `GetTenant()`
8080
- Utility methods for parsing and context access.
8181

82+
### Transport security (HTTP vs HTTPS)
83+
84+
The transport protocol is supplied by the caller when constructing `PcRestProxy`
85+
(the `webProtocolName` argument, typically `"https"` or `"http"`).
86+
87+
- **HTTPS is recommended for all real and production environments.** Credentials
88+
(Basic authentication and token-based authentication) and session cookies are only
89+
protected in transit when HTTPS is used.
90+
- **HTTP is allowed but not recommended.** It is supported on purpose so that customers
91+
can evaluate OpenText Enterprise Performance Engineering (LoadRunner Enterprise) in
92+
development/test environments that do not have an SSL certificate configured. Over plain
93+
HTTP, credentials and cookies are transmitted unencrypted; do not use HTTP outside of
94+
isolated, non-production environments.
95+
96+
### Full interface reference
97+
98+
Every method declared in `PcRestProxyClient` is documented below. Methods marked
99+
`@Deprecated` are retained for backward compatibility; prefer the lower-case named
100+
replacements.
101+
102+
#### Authentication / session
103+
104+
- `boolean authenticate(String userName, String password)`
105+
- Opens an authenticated session. When the proxy is configured for token authentication,
106+
`userName`/`password` are the client id key and secret key; otherwise they are the ALM
107+
user name and password. Returns `true` on success.
108+
- `boolean logout()`
109+
- Closes the authenticated session. Returns `true` on success.
110+
- `String GetPcServer()`
111+
- Returns the resolved enterprise Performance Engineering server (host) the proxy targets.
112+
- `String GetTenant()`
113+
- Returns the resolved tenant suffix associated with the server, or an empty string when
114+
no tenant is present.
115+
116+
#### Run lifecycle
117+
118+
- `PcRunResponse startRun(int testId, int testInstanceId, TimeslotDuration timeslotDuration, String postRunAction, boolean vudsMode, int timeslot)`
119+
- Starts a performance run for the given test and test instance, using the supplied
120+
timeslot duration, post-run action, VUDs mode, and timeslot id. Returns the created run
121+
(including its id and state).
122+
- `boolean stopRun(int runId, String stopMode)`
123+
- Stops the run identified by `runId` using the given stop mode (for example a graceful or
124+
immediate stop). Returns `true` on success.
125+
- `PcRunResponse getRunData(int runId)`
126+
- Returns the current data/state for the specified run.
127+
128+
#### Run artifacts and logs
129+
130+
- `PcRunResults getRunResults(int runId)`
131+
- Returns the collection of result artifacts available for the run.
132+
- `boolean GetRunResultData(int runId, int resultId, String localFilePath)`
133+
- Downloads a single run result (identified by `resultId`) to `localFilePath`. Returns
134+
`true` on success.
135+
- `PcRunEventLog getRunEventLog(int runId)`
136+
- Returns the event log records produced during the run.
137+
138+
#### Script management
139+
140+
- `int uploadScript(String testFolderPath, boolean overwrite, boolean runtimeOnly, boolean keepCheckedOut, String scriptPath)`
141+
- Uploads the script at `scriptPath` into the test plan folder `testFolderPath`. Flags
142+
control overwrite behavior, runtime-only upload, and whether the script is kept checked
143+
out. Returns the new script id.
144+
- `PcScripts getScripts()`
145+
- Returns all scripts visible in the current project.
146+
- `PcScript getScript(int Id)`
147+
- Returns the script identified by its numeric id.
148+
- `PcScript getScript(String testFolderPath, String scriptName)`
149+
- Returns the script located by folder path and script name.
150+
- `boolean deleteScript(int scriptId)`
151+
- Deletes the script identified by `scriptId`. Returns `true` on success.
152+
153+
#### Test plan folders
154+
155+
- `PcTestPlanFolders getTestPlanFolders()`
156+
- Returns the test plan folder structure for the project.
157+
- `boolean verifyTestPlanFolderExist(String path)`
158+
- Returns `true` if the test plan folder at `path` exists.
159+
- `PcTestPlanFolder createTestPlanFolder(String existingPath, String name)`
160+
- Creates a folder named `name` under the already existing folder `existingPath` and
161+
returns it.
162+
- `ArrayList<PcTestPlanFolder> createTestPlanFolders(String[] paths)`
163+
- Creates all folders required by the supplied full `paths`, creating intermediate folders
164+
as needed, and returns the created folders.
165+
- `ArrayList<PcTestPlanFolder> createPcTestPlanFolders(ArrayList<String[]> stringsOfExistingPathFromSubjectAndOfFolderToCreate)`
166+
- Lower-level variant of `createTestPlanFolders` that accepts, for each folder, a
167+
`[existingParentPath, folderNameToCreate]` pair. Returns the created folders.
168+
169+
#### Performance test definitions
170+
171+
- `Test createOrUpdateTestFromYamlTest(String testString)`
172+
- Creates or updates a test from a full YAML test definition (name, folder, and content in
173+
one document). Returns the resulting test.
174+
- `Test createOrUpdateTestFromYamlContent(String testName, String testFolderPath, String testOrContent)`
175+
- Creates or updates the test named `testName` under `testFolderPath` from a YAML content
176+
(or test) document. Returns the resulting test.
177+
- `Test createOrUpdateTest(String testName, String testFolderPath, String xml)`
178+
- Creates or updates the test named `testName` under `testFolderPath` from an XML content
179+
document. Returns the resulting test.
180+
- `Test createOrUpdateTest(String testName, String testFolderPath, Content content)`
181+
- Creates or updates the test named `testName` under `testFolderPath` from a `Content`
182+
entity. Returns the resulting test.
183+
- `Test getTest(int testId)`
184+
- Returns the full test definition for `testId`.
185+
- `PcTest getTestData(int testId)`
186+
- Returns metadata for the test identified by `testId`.
187+
- `Test updateTest(int testId, Content content)`
188+
- Replaces the content of an existing test identified by `testId`. Returns the updated test.
189+
- `boolean deleteTest(int testId)`
190+
- Deletes the test identified by `testId`. Returns `true` on success.
191+
192+
#### Test sets, test instances and timeslots
193+
194+
- `PcTestSets getAllTestSets()`
195+
- Returns all test sets in the project.
196+
- `PcTestSets GetAllTestSets()` *(deprecated)*
197+
- Deprecated alias for `getAllTestSets()`.
198+
- `PcTestInstances getTestInstancesByTestId(int testId)`
199+
- Returns the test instances associated with `testId`.
200+
- `int createTestInstance(int testId, int testSetId)`
201+
- Creates a test instance linking `testId` to the test set `testSetId`. Returns the new
202+
test instance id.
203+
- `PcTestSetFolders getTestSetFolders()`
204+
- Returns the test set folder structure for the project.
205+
- `PcTestSetFolder createTestSetFolder(int parentId, String name)`
206+
- Creates a test set folder named `name` under the folder `parentId` and returns it.
207+
- `PcTestSet createTestSet(String testSetName, int testSetParentId, String testSetComment)`
208+
- Creates a test set named `testSetName` under `testSetParentId` with the supplied comment
209+
and returns it.
210+
- `PcTestSet createTestSet(String testSetName, int testSetParentId)` *(default)*
211+
- Convenience overload that creates a test set with an empty comment.
212+
- `Timeslots GetOpenTimeslotsByTestId(int testId)`
213+
- Returns the open timeslots available for `testId`.
214+
215+
#### Trend reporting
216+
217+
- `int addTrendReport(String name, String description)`
218+
- Creates a trend report with the given name and description. Returns the new trend report
219+
id.
220+
- `int addTrendReport(String name)` *(default)*
221+
- Convenience overload that creates a trend report with an empty description.
222+
- `TrendReportTransactionDataRoot getTrendReportByXML(String trendReportId, int runId)`
223+
- Returns the transaction-level trend report data for the given trend report and run.
224+
- `boolean updateTrendReport(String trendReportId, TrendReportRequest trendReportRequest)`
225+
- Updates the trend report identified by `trendReportId` with the supplied request. Returns
226+
`true` on success.
227+
- `InputStream getTrendingPDF(String trendReportId)`
228+
- Returns the trend report rendered as a PDF stream. The caller is responsible for closing
229+
the stream.
230+
- `ArrayList<PcTrendedRun> getTrendReportMetaData(String trendReportId)`
231+
- Returns metadata describing the runs included in the trend report.
232+
233+
#### Helpers
234+
235+
- `int extractTestIdFromString(String value)`
236+
- Extracts a test id encoded inside a string (for example `ID:'123'`). Returns `0` when no
237+
id is found.
238+
- `Content readYaml(String yamlContent)`
239+
- Parses a YAML content document into a `Content` entity.
240+
82241
## Test documentation
83242

84243
- Unit tests guide:

pom.xml

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<modelVersion>4.0.0</modelVersion>
44
<groupId>com.microfocus.adm.performancecenter</groupId>
55
<artifactId>plugins-common</artifactId>
6-
<version>1.2.3</version>
6+
<version>1.2.4</version>
77
<packaging>jar</packaging>
88
<name>OpenText Enterprise Performance Engineering plugins common</name>
99
<description>The plugin is a common code for plugins integrated with OpenText Enterprise Performance Engineering via public REST API.</description>
@@ -29,7 +29,7 @@
2929
<role>Plugin Owner and LoadRunner Enterprise RnD</role>
3030
</roles>
3131
<organization>LoadRunner Enterprise</organization>
32-
<organizationUrl>https://www.opentext.com/products/loadrunner-enterprise</organizationUrl>
32+
<organizationUrl>https://www.opentext.com/products/enterprise-performance-engineering</organizationUrl>
3333
</developer>
3434
</developers>
3535
<scm>
@@ -54,11 +54,6 @@
5454
<artifactId>commons-codec</artifactId>
5555
<version>1.16.0</version>
5656
</dependency>
57-
<dependency>
58-
<groupId>org.apache.httpcomponents.client5</groupId>
59-
<artifactId>httpclient5</artifactId>
60-
<version>5.2.1</version>
61-
</dependency>
6257
<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
6358
<dependency>
6459
<groupId>commons-logging</groupId>

src/main/java/com/microfocus/adm/performancecenter/plugins/common/rest/PcRestProxy.java

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.apache.http.client.ClientProtocolException;
3636
import org.apache.http.client.CookieStore;
3737
import org.apache.http.client.CredentialsProvider;
38+
import org.apache.http.client.config.CookieSpecs;
3839
import org.apache.http.client.config.RequestConfig;
3940
import org.apache.http.client.methods.*;
4041
import org.apache.http.client.protocol.HttpClientContext;
@@ -47,7 +48,6 @@
4748
import org.apache.http.impl.client.CloseableHttpClient;
4849
import org.apache.http.impl.client.HttpClientBuilder;
4950
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
50-
import org.apache.http.protocol.BasicHttpContext;
5151
import org.apache.http.protocol.HttpContext;
5252
import org.apache.http.util.EntityUtils;
5353
import org.xml.sax.SAXException;
@@ -63,7 +63,7 @@
6363
import java.util.List;
6464
import java.util.stream.Collectors;
6565

66-
import static org.apache.hc.core5.http.HttpStatus.*;
66+
import static org.apache.http.HttpStatus.*;
6767

6868
public class PcRestProxy implements PcRestProxyClient {
6969

@@ -95,7 +95,7 @@ public class PcRestProxy implements PcRestProxyClient {
9595
private String proxyHostName;
9696
private int proxyPort;
9797
private final CloseableHttpClient client;
98-
private final HttpContext context;
98+
private final CookieStore cookieStore;
9999
private final String tenantSuffix;
100100
private final boolean authenticateWithToken;
101101

@@ -123,15 +123,18 @@ public PcRestProxy(
123123
HttpClientBuilder builder = HttpClientBuilder.create()
124124
.setConnectionManager(cxMgr);
125125

126+
// Use the RFC 6265 cookie policy so that session-deletion cookies (e.g. the
127+
// LWSSO logout cookie with "expires=Thu, 01 Jan 1970 00:00:00 GMT") are parsed
128+
// without emitting "Invalid cookie header" warnings from the legacy date parser.
129+
RequestConfig.Builder requestConfigBuilder = RequestConfig.custom()
130+
.setCookieSpec(CookieSpecs.STANDARD);
131+
126132
// Proxy setup
127133
if (proxyOutURL != null && !proxyOutURL.isEmpty()) {
128134
getProxyDataFromURL(proxyOutURL);
129135
HttpHost proxy = new HttpHost(this.proxyHostName, this.proxyPort, this.proxyScheme);
130136

131-
RequestConfig config = RequestConfig.custom()
132-
.setProxy(proxy)
133-
.build();
134-
builder.setDefaultRequestConfig(config);
137+
requestConfigBuilder.setProxy(proxy);
135138

136139
if (proxyUser != null && !proxyUser.isEmpty()) {
137140
CredentialsProvider credsProvider = new BasicCredentialsProvider();
@@ -142,11 +145,22 @@ public PcRestProxy(
142145
builder.setDefaultCredentialsProvider(credsProvider);
143146
}
144147
}
148+
builder.setDefaultRequestConfig(requestConfigBuilder.build());
145149
this.client = builder.build();
146150

147-
this.context = new BasicHttpContext();
148-
CookieStore cookieStore = new BasicCookieStore();
149-
this.context.setAttribute(HttpClientContext.COOKIE_STORE, cookieStore);
151+
this.cookieStore = new BasicCookieStore();
152+
}
153+
154+
/**
155+
* Builds a fresh per-request {@link HttpContext} backed by the shared, thread-safe
156+
* {@link CookieStore}. A new context is created for every request so that a single
157+
* {@code PcRestProxy} instance can safely be used concurrently from multiple threads,
158+
* while all threads continue to share the same authenticated session cookies.
159+
*/
160+
private HttpContext createContext() {
161+
HttpClientContext ctx = HttpClientContext.create();
162+
ctx.setCookieStore(cookieStore);
163+
return ctx;
150164
}
151165

152166
public static Content getContentFromXmlOrYamlString(String xmlOrYamlTest) {
@@ -456,7 +470,7 @@ public boolean logout() throws PcException, ClientProtocolException, IOException
456470
}
457471

458472
protected String executeRequest(HttpRequestBase request) throws PcException, IOException {
459-
try (CloseableHttpResponse response = client.execute(request, context)) {
473+
try (CloseableHttpResponse response = client.execute(request, createContext())) {
460474
if (!isOk(response)) {
461475
String message;
462476
try {
@@ -474,7 +488,7 @@ protected String executeRequest(HttpRequestBase request) throws PcException, IOE
474488
}
475489

476490
protected CloseableHttpResponse executeRawRequest(HttpRequestBase request) throws PcException, IOException {
477-
CloseableHttpResponse response = client.execute(request, context);
491+
CloseableHttpResponse response = client.execute(request, createContext());
478492
if (!isOk(response)) {
479493
try {
480494
String content = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);

0 commit comments

Comments
 (0)