Skip to content

Commit 243e28d

Browse files
authored
Add support for creating Freezer Manager freezer hierarchies via StorageController APIs (#36)
## version 3.1.0 *Released*: 20 September 2022 * Add support for creating Freezer Manager freezer hierarchies via StorageController APIs (earliest compatible LabKey Server version: 22.10.0) * CreateCommand, UpdateCommand, DeleteCommand * Restore proactive authentication behavior. A change in v3.0.0 caused some invocations of `@NoPermissionsRequired` actions (e.g., `GetContainersCommand`) to use guest credentials instead of the configured user credentials. The library now always authenticates using the configured credentials, matching pre-v3.0.0 behavior.
1 parent 6ba3150 commit 243e28d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+722
-188
lines changed

labkey-client-api/CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
11
# The LabKey Remote API Library for Java - Change Log
22

3+
## version 3.1.0
4+
*Released*: 20 September 2022
5+
* Add support for creating Freezer Manager freezer hierarchies via StorageController APIs (earliest compatible LabKey Server version: 22.10.0)
6+
* CreateCommand, UpdateCommand, DeleteCommand
7+
* Restore proactive authentication behavior. A change in v3.0.0 caused some invocations of `@NoPermissionsRequired`
8+
actions (e.g., `GetContainersCommand`) to use guest credentials instead of the configured user credentials. The library
9+
now always authenticates using the configured credentials, matching pre-v3.0.0 behavior.
10+
311
## version 3.0.0
412
*Released*: 14 September 2022
513
* Migrate internal HTTP handling to use Apache HttpClient 5.1.x
14+
* Migrate from preemptive to challenge-response Basic authentication
615
* Switch `StopImpersonatingCommand` to disable redirects (mimicking previous behavior)
716
* Add `Connection.stopImpersonating()` and deprecate `stopImpersonate()`
817
* Remove deprecated methods:

labkey-client-api/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ compatibility with LabKey Server versions.
2121
### Dependency Declaration
2222
To declare a dependency on this jar file, you can use the following in Gradle
2323

24-
```compile(group: 'org.labkey.api', name: 'labkey-client-api', version: '1.2.0')```
24+
```compile(group: 'org.labkey.api', name: 'labkey-client-api', version: '3.1.0')```
2525

2626
If using the LabKey Gradle plugins and building a LabKey module, it is best to
2727
use this utility method instead to facilitate testing of any local changes to
@@ -59,7 +59,7 @@ When your feature development is done, you should:
5959

6060
- Update the version number in the `build.gradle` file to the next logical SNAPSHOT version corresponding to your changes
6161
following the [SemVer](https://semver.org/) guidelines. Make sure this is a SNAPSHOT version (e.g., `1.2.3-SNAPSHOT`).
62-
- Update the [change log](CHANGELOG.md) to document what has changed. You can leave the release date and version alone at this
62+
- Update the [change log](CHANGELOG.md) to document what has changed. You can leave the release date and version alone at this
6363
point; they will get updated when the next release is published.
6464
- **TBD** Run tests using your SNAPSHOT version of the tests
6565
- Merge your branch into develop if appropriate tests are passing.

labkey-client-api/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ repositories {
5757

5858
group "org.labkey.api"
5959

60-
version "3.1.0-SNAPSHOT"
60+
version "3.2.0-SNAPSHOT"
6161

6262
dependencies {
6363
api ("com.googlecode.json-simple:json-simple:${jsonSimpleVersion}")

labkey-client-api/src/org/labkey/remoteapi/Command.java

Lines changed: 25 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -441,18 +441,12 @@ protected ResponseType createResponse(String text, int status, String contentTyp
441441
* @throws CommandException Thrown if there is a problem encoding or parsing the URL
442442
* @throws URISyntaxException Thrown if there is a problem parsing the base URL in the connection.
443443
*/
444+
445+
// TODO: For next major release, remove CommandException from throws list
444446
protected HttpUriRequest getHttpRequest(Connection connection, String folderPath) throws CommandException, URISyntaxException
445447
{
446-
// TODO (Dave 11/11/14 -- as far as I can tell the default of the AuthSchemes is to automatically handle challenges
447-
// method.setDoAuthentication(true);
448-
449-
// NOTE: Fairly sure that the "unescaped" comment below is obsolete
450-
// TODO: Combine getActionUrl() and addParameters() into a single method
451-
//construct a URI from the results of the getActionUrl method
452-
//note that this method returns an unescaped URL, so pass
453-
//false for the second parameter to escape it
454-
URI uri = getActionUrl(connection, folderPath);
455-
uri = addParameters(uri);
448+
//construct a URI from connection base URI, folder path, and current parameters
449+
URI uri = createURI(connection, folderPath);
456450

457451
return createRequest(uri);
458452
}
@@ -469,17 +463,14 @@ protected HttpUriRequest createRequest(URI uri)
469463
}
470464

471465
/**
472-
* Returns the portion of the URL before the query string for this command.
473-
* <p>
474-
* Note that the URL returned should <em>not</em> be encoded, as the calling function will encode it.
475-
* <p>
476-
* For example: "http://localhost:8080/labkey/MyProject/MyFolder/selectRows.api"
466+
* Returns a full URI for this Command, including base URI, folder path, and query string.
467+
*
477468
* @param connection The connection to use.
478469
* @param folderPath The folder path to use.
479-
* @return The URL
470+
* @return The URI
480471
* @throws URISyntaxException if the uri constructed from the parameters is malformed
481472
*/
482-
private URI getActionUrl(Connection connection, String folderPath) throws URISyntaxException
473+
private URI createURI(Connection connection, String folderPath) throws URISyntaxException
483474
{
484475
URI uri = connection.getBaseURI();
485476

@@ -508,52 +499,34 @@ private URI getActionUrl(Connection connection, String folderPath) throws URISyn
508499
if (!actionName.endsWith(".api"))
509500
path.append(".api");
510501

511-
return new URIBuilder(uri).setPath(path.toString()).build();
512-
}
502+
URIBuilder builder = new URIBuilder(uri).setPath(path.toString());
513503

514-
/**
515-
* Adds all parameters to the passed URI
516-
* <p>
517-
* @return The URI with parameters added
518-
* @throws CommandException Thrown if there is a problem building the URI
519-
*/
520-
protected URI addParameters(URI uri) throws CommandException, URISyntaxException
521-
{
522504
Map<String, Object> params = getParameters();
523505

524506
//add the required version if it's > 0
525507
if (getRequiredVersion() > 0)
526508
params.put(CommonParameters.apiVersion.name(), getRequiredVersion());
527509

528-
if (params.isEmpty())
529-
return uri;
530-
531-
URIBuilder builder = new URIBuilder(uri);
532-
533-
for (String name : params.keySet())
510+
if (!params.isEmpty())
534511
{
535-
Object value = params.get(name);
536-
if (value instanceof Collection<?> col)
512+
for (String name : params.keySet())
537513
{
538-
for (Object o : col)
514+
Object value = params.get(name);
515+
if (value instanceof Collection<?> col)
539516
{
540-
addParameter(builder, name, o);
517+
for (Object o : col)
518+
{
519+
addParameter(builder, name, o);
520+
}
521+
}
522+
else
523+
{
524+
addParameter(builder, name, value);
541525
}
542-
}
543-
else
544-
{
545-
addParameter(builder, name, value);
546526
}
547527
}
548528

549-
try
550-
{
551-
return builder.build();
552-
}
553-
catch (URISyntaxException e)
554-
{
555-
throw new CommandException(e.getMessage());
556-
}
529+
return builder.build();
557530
}
558531

559532
private void addParameter(URIBuilder builder, String name, Object value)
@@ -592,7 +565,7 @@ public double getRequiredVersion()
592565
* Sets the required version number for this API call.
593566
* By default, the required version is 8.3, meaning that
594567
* this call requires LabKey Server version 8.3 or higher.
595-
* Set this to a higher number to required a later
568+
* Set this to a higher number to require a later
596569
* version of the server.
597570
* @param requiredVersion The new required version
598571
*/
@@ -606,8 +579,9 @@ public void setRequiredVersion(double requiredVersion)
606579
* to copy their own data members
607580
* @return A copy of this object
608581
*/
582+
// TODO: For next major release, genericize this return value (Command<ResponseType>)
609583
public Command copy()
610584
{
611-
return new Command(this);
585+
return new Command<>(this);
612586
}
613587
}

labkey-client-api/src/org/labkey/remoteapi/CommandResponse.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ public Command getSourceCommand()
132132
* @return The parsed data as a property map.
133133
*/
134134
@SuppressWarnings("unchecked")
135-
public Map<String,Object> getParsedData()
135+
public Map<String, Object> getParsedData()
136136
{
137137
if(null == _data && null != getText()
138138
&& null != _contentType && _contentType.contains(Command.CONTENT_TYPE_JSON))
@@ -174,7 +174,7 @@ public <T> T getProperty(String path)
174174
* @return The property value, or null if not found.
175175
*/
176176
@SuppressWarnings("unchecked")
177-
protected <T> T getProperty(String[] path, int pathIndex, Map<String,Object> parent)
177+
protected <T> T getProperty(String[] path, int pathIndex, Map<String, Object> parent)
178178
{
179179
if(null == parent)
180180
return null;
@@ -206,7 +206,7 @@ protected <T> T getProperty(String[] path, int pathIndex, Map<String,Object> par
206206
{
207207
//recurse if prop is non-null and instance of map
208208
return (null != prop && prop instanceof Map)
209-
? (T)getProperty(path, pathIndex + 1, (Map<String,Object>)prop)
209+
? (T)getProperty(path, pathIndex + 1, (Map<String, Object>)prop)
210210
: null;
211211
}
212212
}

labkey-client-api/src/org/labkey/remoteapi/Connection.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
import org.labkey.remoteapi.security.ImpersonateUserCommand;
3939
import org.labkey.remoteapi.security.LogoutCommand;
4040
import org.labkey.remoteapi.security.StopImpersonatingCommand;
41-
import org.labkey.remoteapi.security.WhoAmICommand;
4241

4342
import java.io.IOException;
4443
import java.net.URI;
@@ -120,6 +119,7 @@ public class Connection
120119
private Integer _proxyPort;
121120
private String _csrf;
122121
private String _sessionId;
122+
private boolean _firstRequest = true;
123123

124124
// The user email when impersonating a user
125125
private String _impersonateUser;
@@ -278,19 +278,19 @@ private HttpClientConnectionManager getSelfSignedConnectionManager()
278278
}
279279

280280
/**
281-
* If necessary, prime the Connection for non-GET requests.
282-
* Executes a dummy command to trigger authentication and populate CSRF and session info.
281+
* If first request, prime the Connection by forcing authentication and populating CSRF and session info.
283282
* @param request HttpRequest that is about to be executed
284283
*/
285284
protected void beforeExecute(HttpRequest request)
286285
{
287-
if (null == _csrf &&
288-
request instanceof HttpUriRequestBase && !"GET".equals(request.getMethod()))
286+
if (_firstRequest)
289287
{
290-
// make a request to get a JSESSIONID
288+
// Make an initial request to ensure login (especially important when invoking @RequiresNoPermission actions),
289+
// get a JSESSIONID, and get a CSRF token
291290
try
292291
{
293-
new WhoAmICommand().execute(this, "/");
292+
_firstRequest = false;
293+
ensureAuthenticated();
294294
}
295295
catch (Exception ignored)
296296
{
@@ -322,6 +322,7 @@ protected void afterExecute()
322322
* @throws IOException if there is an IO problem executing the command to ensure login
323323
* @throws CommandException if the server returned a non-success status code.
324324
*/
325+
// TODO: For next major release, stop returning CloseableHttpClient?
325326
public CloseableHttpClient ensureAuthenticated() throws IOException, CommandException
326327
{
327328
EnsureLoginCommand command = new EnsureLoginCommand();
@@ -335,6 +336,7 @@ public CloseableHttpClient ensureAuthenticated() throws IOException, CommandExce
335336
* @throws IOException if there is an IO problem executing the command to ensure logout
336337
* @throws CommandException if the server returned a non-success status code.
337338
*/
339+
// TODO: For next major release, stop returning CloseableHttpClient?
338340
public CloseableHttpClient logout() throws IOException, CommandException
339341
{
340342
LogoutCommand command = new LogoutCommand();
@@ -492,7 +494,7 @@ public boolean isAcceptSelfSignedCerts()
492494
}
493495

494496
/**
495-
* Sets the accept self-signed certificates option. Set to false
497+
* Sets the accept-self-signed certificates option. Set to false
496498
* to disable automatic acceptance of self-signed SSL certificates
497499
* when using HTTPS.
498500
* NOTE: Changing this setting will force the underlying http client to be recreated.
@@ -502,7 +504,6 @@ public boolean isAcceptSelfSignedCerts()
502504
*/
503505
public Connection setAcceptSelfSignedCerts(boolean acceptSelfSignedCerts)
504506
{
505-
// Handled in getHttpClient using 4.3.x approach documented here http://stackoverflow.com/questions/19517538/ignoring-ssl-certificate-in-apache-httpclient-4-3
506507
_acceptSelfSignedCerts = acceptSelfSignedCerts;
507508
_client = null;
508509
return this;

labkey-client-api/src/org/labkey/remoteapi/PostCommand.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public PostCommand(String controllerName, String actionName)
6161
super(controllerName, actionName);
6262
}
6363

64-
public PostCommand(PostCommand source)
64+
public PostCommand(PostCommand<ResponseType> source)
6565
{
6666
super(source);
6767
if (null != source.getJsonObject())
@@ -120,6 +120,6 @@ protected HttpUriRequest createRequest(URI uri)
120120
@Override
121121
public PostCommand copy()
122122
{
123-
return new PostCommand(this);
123+
return new PostCommand<>(this);
124124
}
125125
}

labkey-client-api/src/org/labkey/remoteapi/assay/AssayListCommand.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ public void setId(Integer id)
117117
_id = id;
118118
}
119119

120+
@Override
120121
protected AssayListResponse createResponse(String text, int status, String contentType, JSONObject json)
121122
{
122123
return new AssayListResponse(text, status, contentType, json, this.copy());
@@ -134,9 +135,10 @@ public JSONObject getJsonObject()
134135
return obj;
135136
}
136137

138+
@Override
137139
public Map<String, Object> getParameters()
138140
{
139-
Map<String,Object> params = new HashMap<String,Object>();
141+
Map<String, Object> params = new HashMap<>();
140142
if(null != getName())
141143
params.put("name", getName());
142144
if(null != getType())

labkey-client-api/src/org/labkey/remoteapi/assay/AssayListResponse.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
*/
1616
package org.labkey.remoteapi.assay;
1717

18-
import org.labkey.remoteapi.CommandResponse;
1918
import org.json.simple.JSONObject;
19+
import org.labkey.remoteapi.CommandResponse;
2020

2121
import java.util.List;
2222
import java.util.Map;
@@ -52,7 +52,7 @@ public AssayListResponse(String text, int statusCode, String contentType, JSONOb
5252
* about the particular assay definition.
5353
* @return The list of definitions.
5454
*/
55-
public List<Map<String,Object>> getDefinitions()
55+
public List<Map<String, Object>> getDefinitions()
5656
{
5757
return getProperty("definitions");
5858
}
@@ -62,7 +62,7 @@ public List<Map<String,Object>> getDefinitions()
6262
* @param name The name of the assay definition to find.
6363
* @return The assay definition or null if not found.
6464
*/
65-
public Map<String,Object> getDefinition(String name)
65+
public Map<String, Object> getDefinition(String name)
6666
{
6767
return findObject(getDefinitions(), "name", name);
6868
}
@@ -72,7 +72,7 @@ public Map<String,Object> getDefinition(String name)
7272
* @param id The id of the assay definition to find.
7373
* @return The assay definition or null if not found.
7474
*/
75-
public Map<String,Object> getDefinition(int id)
75+
public Map<String, Object> getDefinition(int id)
7676
{
7777
return findObject(getDefinitions(), "id", String.valueOf(id));
7878
}

labkey-client-api/src/org/labkey/remoteapi/assay/Batch.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
*/
2828
public class Batch extends ExpObject
2929
{
30-
private List<Run> _runs = new ArrayList<Run>();
30+
private List<Run> _runs = new ArrayList<>();
3131

3232
public Batch()
3333
{

labkey-client-api/src/org/labkey/remoteapi/assay/GetProtocolCommand.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public GetProtocolCommand(long protocolId, boolean copy)
3434
@Override
3535
public Map<String, Object> getParameters()
3636
{
37-
Map<String,Object> params = new HashMap<>();
37+
Map<String, Object> params = new HashMap<>();
3838
if (_protocolId != null)
3939
{
4040
params.put("protocolId", _protocolId);

labkey-client-api/src/org/labkey/remoteapi/assay/Run.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@
3030
public class Run extends ExpObject
3131
{
3232
private String _comment;
33-
private List<Data> _dataInputs = new ArrayList<Data>();
34-
private List<Data> _dataOutputs = new ArrayList<Data>();
33+
private List<Data> _dataInputs = new ArrayList<>();
34+
private List<Data> _dataOutputs = new ArrayList<>();
3535
private List<Material> _materialInputs = new ArrayList<>();
3636
private List<Material> _materialOutputs = new ArrayList<>();
3737
private String _lsid;

labkey-client-api/src/org/labkey/remoteapi/assay/nab/NAbRunsCommand.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,16 @@ public NAbRunsCommand(NAbRunsCommand source)
6464
_calculateNeut = source._calculateNeut;
6565
}
6666

67+
@Override
6768
protected NAbRunsResponse createResponse(String text, int status, String contentType, JSONObject json)
6869
{
6970
return new NAbRunsResponse(text, status, contentType, json, this.copy());
7071
}
7172

73+
@Override
7274
public Map<String, Object> getParameters()
7375
{
74-
Map<String,Object> params = super.getParameters();
76+
Map<String, Object> params = super.getParameters();
7577

7678
if (null != getAssayName())
7779
params.put("assayName", getAssayName());

0 commit comments

Comments
 (0)