Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve error handling and logging #237

Merged
merged 2 commits into from
Jan 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## webrepl

A quick and dirty REPL for JPv3's IIIF Cookbook recipes.
A quick and dirty, single-threaded REPL for JPv3's IIIF Cookbook recipes.

### How to Build

Expand Down
26 changes: 21 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
<!-- Dependency versions -->
<microhttp.version>0.11</microhttp.version>
<jpv3.version>0.0.0-SNAPSHOT</jpv3.version>
<freelib.utils.version>5.0.7</freelib.utils.version>
<freelib.utils.version>5.0.10</freelib.utils.version>

<!-- Configuring Sonar to use the right (i.e., webrepl) branch -->
<sonar.branch.target>webrepl</sonar.branch.target>
Expand All @@ -60,6 +60,8 @@
<!-- Test dependency versions -->
<junit.version>5.11.0</junit.version>
<mockito.version>5.14.2</mockito.version>
<awaitility.version>4.2.2</awaitility.version>
<system.lambda.version>1.2.1</system.lambda.version>

<!-- Skip the requirement that none of the dependencies are snapshot versions -->
<enforcer.skip>true</enforcer.skip>
Expand Down Expand Up @@ -116,6 +118,18 @@
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.stefanbirkner</groupId>
<artifactId>system-lambda</artifactId>
<version>${system.lambda.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<version>${awaitility.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down Expand Up @@ -169,7 +183,7 @@
</filters>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>info.freelibrary.iiif.webrepl.Server</mainClass>
<mainClass>info.freelibrary.iiif.webrepl.WebRepl</mainClass>
</transformer>
</transformers>
</configuration>
Expand Down Expand Up @@ -241,7 +255,8 @@
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>${jacoco.agent.arg} -javaagent:${org.mockito:mockito-core:jar}</argLine>
<argLine>${jacoco.agent.arg} -javaagent:${org.mockito:mockito-core:jar}
--add-opens java.base/java.util=ALL-UNNAMED -Xshare:off</argLine>
<environmentVariables>
<HTTP_PORT>${test.http.port}</HTTP_PORT>
</environmentVariables>
Expand All @@ -255,7 +270,8 @@
<systemPropertyVariables>
<server.port>${test.http.port}</server.port>
</systemPropertyVariables>
<argLine>--add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED</argLine>
<argLine>--add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED
-Xshare:off</argLine>
</configuration>
</plugin>

Expand Down Expand Up @@ -396,7 +412,7 @@
<parent>
<artifactId>freelib-parent</artifactId>
<groupId>info.freelibrary</groupId>
<version>12.0.0</version>
<version>12.0.3</version>
</parent>

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
/**
* A diagnostic consumer for handling rejected code snippets.
*/
public class DiagConsumer implements Consumer<Diag> {
public class DiagnosticConsumer implements Consumer<Diag> {

/** A delimiter for the end of problematic code. */
private static final String END = "]]";
Expand Down Expand Up @@ -42,7 +42,7 @@ public class DiagConsumer implements Consumer<Diag> {
*
* @param aBuffer An output buffer
*/
public DiagConsumer(final StringBuilder aBuffer) {
public DiagnosticConsumer(final StringBuilder aBuffer) {
myBuffer = aBuffer;
}

Expand Down Expand Up @@ -71,7 +71,7 @@ public void accept(final Diag aDiagnostic) {
}

// Add line numbers to what's returned
code = StringUtils.addLineNumbers(myBuffer.toString());
code = StringUtils.addLineNumbers(myBuffer.toString().trim());

// Zero out the output buffer
myBuffer.setLength(0);
Expand Down
42 changes: 42 additions & 0 deletions src/main/java/info/freelibrary/iiif/webrepl/EnvOptions.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@

package info.freelibrary.iiif.webrepl;

import java.time.Duration;

import org.microhttp.Options;

import info.freelibrary.util.Constants;
import info.freelibrary.util.Env;

/**
* The server's environmental options.
*/
public class EnvOptions {

/** The maximum request size. */
private static final int DEFAULT_MAX_REQ_SIZE = 1_024 * 1_024;

/** The default port at which the server listens. */
private static final int DEFAULT_PORT = 8888;

/** The read buffer size. */
private static final int DEFAULT_READ_BUF_SIZE = 1_024 * 64;

/** The request timeout. */
private static final long DEFAULT_REQ_TIMEOUT = 60L;

/**
* Gets the environmental options.
*
* @return The configuration options
*/
public Options getOpts() {
final int port = Env.get(Config.HTTP_PORT, DEFAULT_PORT);
final int reqSize = Env.get(Config.MAX_REQUEST_SIZE, DEFAULT_MAX_REQ_SIZE);
final int bufSize = Env.get(Config.READ_BUFFER_SIZE, DEFAULT_READ_BUF_SIZE);
final long timeout = (long) Env.get(Config.REQUEST_TIMEOUT, DEFAULT_REQ_TIMEOUT);

return Options.builder().withHost(Constants.INADDR_ANY).withPort(port).withMaxRequestSize(reqSize)
.withRequestTimeout(Duration.ofSeconds(timeout)).withReadBufferSize(bufSize).build();
}
}
93 changes: 93 additions & 0 deletions src/main/java/info/freelibrary/iiif/webrepl/Imports.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@

package info.freelibrary.iiif.webrepl;

import static info.freelibrary.util.Constants.EOL;
import static info.freelibrary.util.StringUtils.addLineNumbers;
import static info.freelibrary.util.StringUtils.indent;
import static java.util.stream.Collectors.joining;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.nio.file.Files;
import java.nio.file.Path;

import info.freelibrary.util.warnings.PMD;
import info.freelibrary.util.warnings.Sonar;

/**
* A string of imports.
*/
public class Imports {

/** A label for the display of imports in the logs. */
private static final String LABEL = "Imports:";

/** A string of imports. */
private final String myImports;

/**
* Creates a new imports string.
*
* @throws IOException If there is trouble reading from the imports file
*/
public Imports() throws IOException {
File importsFile = Path.of("/etc/jshell/imports.jsh").toFile();

// Check to see if we're running from the Maven build
if (!importsFile.exists()) {
importsFile = Path.of("src/main/docker/imports.jsh").toFile();
}

try (BufferedReader reader = Files.newBufferedReader(importsFile.toPath())) {
myImports = reader.lines().filter(line -> !line.isBlank()).collect(joining(EOL));
}
}

/**
* Gets all the imports.
*
* @return An imports string
*/
@SuppressWarnings({ Sonar.SYSTEM_OUT_ERR, PMD.SYSTEM_PRINTLN })
public String getAll() {
if (myImports.isEmpty()) {
System.err.println();
} else {
System.err.println(EOL + LABEL);
System.err.println(indent(addLineNumbers(myImports), 2));
}

return myImports;
}

/**
* Gets all the imports that are referenced in the supplied code snippet.
*
* @param aSnippet A code snippet to check for imports
* @return An imports string
* @throws IOException if there is trouble parsing the imports
*/
@SuppressWarnings({ Sonar.SYSTEM_OUT_ERR, PMD.SYSTEM_PRINTLN })
public String getReferenced(final String aSnippet) throws IOException {
final String imports;

try (BufferedReader reader = new BufferedReader(new StringReader(myImports))) {
imports = reader.lines().filter(line -> {
final String className = line.substring(line.lastIndexOf('.') + 1, line.length() - 1);
return aSnippet == null || aSnippet.contains(className);
}).collect(joining(EOL)).trim();
}

// The above gets imports for the user, the below shows the imported imports in the logs
if (imports.isEmpty()) {
System.err.println();
} else {
System.err.println(EOL + LABEL);
System.err.println(indent(addLineNumbers(imports), 2));
}

return imports;
}
}
34 changes: 34 additions & 0 deletions src/main/java/info/freelibrary/iiif/webrepl/ParsingError.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

package info.freelibrary.iiif.webrepl;

import info.freelibrary.util.Constants;
import info.freelibrary.util.StringUtils;

/**
* A {@code WebRepl} parsing error.
*/
public class ParsingError extends Exception {

/** The message template used in constructing the exception message. */
static final String MESSAGE_TEMPLATE =
"Parsing error, but there wasn't a useful diagnostic message. Submitted source code:" + Constants.EOL +
Constants.EOL + "{}";

/** The {@code serialVersionUID} for the ParsingError class. */
private static final long serialVersionUID = 8614571124201029070L;

/**
* Creates a parsing error for the supplied source. This type of parsing error lacks any diagnostic information from
* JShell.
*
* @param aSource A source code snippet
*/
public ParsingError(final String aSource) {
super(StringUtils.format(MESSAGE_TEMPLATE, aSource));
}

@Override
public String toString() {
return getMessage();
}
}
Loading
Loading