update + restructure pom and add missing javadoc

This commit is contained in:
Florian
2021-10-12 17:51:35 +02:00
committed by arnaudroques
parent 098e630a28
commit deda3c2256
18 changed files with 867 additions and 310 deletions

26
src/main/config/rules.xml Normal file
View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<ruleset
comparisonMethod="maven"
xmlns="http://mojo.codehaus.org/versions-maven-plugin/rule/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://mojo.codehaus.org/versions-maven-plugin/rule/2.0.0 https://www.mojohaus.org/versions-maven-plugin/xsd/rule-2.0.0.xsd"
>
<ignoreVersions>
<!-- Ignore Alpha's, Beta's, release candidates and milestones -->
<ignoreVersion type="regex">(?i).*Alpha(?:-?\d+)?</ignoreVersion>
<ignoreVersion type="regex">(?i).*a(?:-?\d+)?</ignoreVersion>
<ignoreVersion type="regex">(?i).*Beta(?:-?\d+)?</ignoreVersion>
<ignoreVersion type="regex">(?i).*-B(?:-?\d+)?</ignoreVersion>
<ignoreVersion type="regex">(?i).*RC(?:-?\d+)?</ignoreVersion>
<ignoreVersion type="regex">(?i).*CR(?:-?\d+)?</ignoreVersion>
<ignoreVersion type="regex">(?i).*M(?:-?\d+)?</ignoreVersion>
</ignoreVersions>
<rules>
<rule groupId="net.sourceforge.plantuml" artifactId="plantuml" comparisonMethod="maven">
<ignoreVersions>
<!-- allow only version like this: 1.20XX.X* -->
<ignoreVersion type="regex"><![CDATA[^(.(?<!1\.20.{2}\.\d))*?$]]></ignoreVersion>
</ignoreVersions>
</rule>
</rules>
</ruleset>

View File

@@ -48,41 +48,69 @@ import net.sourceforge.plantuml.version.Version;
import net.sourceforge.plantuml.error.PSystemError;
import net.sourceforge.plantuml.ErrorUml;
/**
* Delegates the diagram generation from the UML source and the filling of the HTTP response with the diagram in the
* right format. Its own responsibility is to produce the right HTTP headers.
*/
public class DiagramResponse {
/**
* {@link FileFormat} to http content type mapping.
*/
private static final Map<FileFormat, String> CONTENT_TYPE;
/**
* X-Powered-By http header value included in every response by default.
*/
private static final String POWERED_BY = "PlantUML Version " + Version.versionString();
private HttpServletResponse response;
private FileFormat format;
private HttpServletRequest request;
private static final Map<FileFormat, String> CONTENT_TYPE;
static {
Map<FileFormat, String> map = new HashMap<FileFormat, String>();
map.put(FileFormat.PNG, "image/png");
map.put(FileFormat.SVG, "image/svg+xml");
map.put(FileFormat.EPS, "application/postscript");
map.put(FileFormat.UTXT, "text/plain;charset=UTF-8");
map.put(FileFormat.BASE64, "text/plain; charset=x-user-defined");
CONTENT_TYPE = Collections.unmodifiableMap(map);
}
static {
OptionFlags.ALLOW_INCLUDE = false;
if ("true".equalsIgnoreCase(System.getenv("ALLOW_PLANTUML_INCLUDE"))) {
OptionFlags.ALLOW_INCLUDE = true;
}
CONTENT_TYPE = Collections.unmodifiableMap(new HashMap<FileFormat, String>() {{
put(FileFormat.PNG, "image/png");
put(FileFormat.SVG, "image/svg+xml");
put(FileFormat.EPS, "application/postscript");
put(FileFormat.UTXT, "text/plain;charset=UTF-8");
put(FileFormat.BASE64, "text/plain; charset=x-user-defined");
}});
}
public DiagramResponse(HttpServletResponse r, FileFormat f, HttpServletRequest rq) {
response = r;
format = f;
request = rq;
/**
* Response format.
*/
private FileFormat format;
/**
* Http request.
*/
private HttpServletRequest request;
/**
* Http response.
*/
private HttpServletResponse response;
/**
* Create new diagram response instance.
*
* @param res http response
* @param fmt target file format
* @param req http request
*/
public DiagramResponse(HttpServletResponse res, FileFormat fmt, HttpServletRequest req) {
response = res;
format = fmt;
request = req;
}
/**
* Render and send a specific uml diagram.
*
* @param uml textual UML diagram(s) source
* @param idx diagram index of {@code uml} to send
*
* @throws IOException if an input or output exception occurred
*/
public void sendDiagram(String uml, int idx) throws IOException {
response.addHeader("Access-Control-Allow-Origin", "*");
response.setContentType(getContentType());
@@ -114,6 +142,13 @@ public class DiagramResponse {
diagram.exportDiagram(response.getOutputStream(), idx, new FileFormatOption(format));
}
/**
* Is block uml unmodified?
*
* @param blockUml block uml
*
* @return true if unmodified; otherwise false
*/
private boolean notModified(BlockUml blockUml) {
final String ifNoneMatch = request.getHeader("If-None-Match");
final long ifModifiedSince = request.getDateHeader("If-Modified-Since");
@@ -127,7 +162,13 @@ public class DiagramResponse {
return ifNoneMatch.contains(etag);
}
/**
* Produce and send the image map of the uml diagram in HTML format.
*
* @param uml textual UML diagram source
*
* @throws IOException if an input or output exception occurred
*/
public void sendMap(String uml) throws IOException {
response.setContentType(getContentType());
SourceStringReader reader = new SourceStringReader(uml);
@@ -145,15 +186,29 @@ public class DiagramResponse {
}
}
/**
* Check the syntax of the diagram and send a report in TEXT format.
*
* @param uml textual UML diagram source
*
* @throws IOException if an input or output exception occurred
*/
public void sendCheck(String uml) throws IOException {
response.setContentType(getContentType());
SourceStringReader reader = new SourceStringReader(uml);
DiagramDescription desc = reader.outputImage(
new NullOutputStream(), new FileFormatOption(FileFormat.PNG, false));
new NullOutputStream(),
new FileFormatOption(FileFormat.PNG, false)
);
PrintWriter httpOut = response.getWriter();
httpOut.print(desc.getDescription());
}
/**
* Add default header including cache headers to response.
*
* @param blockUml response block uml
*/
private void addHeaderForCache(BlockUml blockUml) {
long today = System.currentTimeMillis();
// Add http headers to force the browser to cache the image
@@ -177,12 +232,22 @@ public class DiagramResponse {
addHeaders(response);
}
/**
* Add default headers to response.
*
* @param response http response
*/
public static void addHeaders(HttpServletResponse response) {
response.addHeader("X-Powered-By", POWERED_BY);
response.addHeader("X-Patreon", "Support us on https://plantuml.com/patreon");
response.addHeader("X-Donate", "https://plantuml.com/paypal");
}
/**
* Get response content type.
*
* @return response content type
*/
private String getContentType() {
return CONTENT_TYPE.get(format);
}

View File

@@ -32,7 +32,6 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sourceforge.plantuml.FileFormat;
import net.sourceforge.plantuml.servlet.utility.UmlExtractor;
/**
@@ -58,6 +57,13 @@ public class MapServlet extends HttpServlet {
dr = null;
}
/**
* Extract UML source from URI.
*
* @param uri the complete URI as returned by `request.getRequestURI()`
*
* @return the encoded UML text
*/
public String getSource(String uri) {
String[] result = uri.split("/map/", 2);
if (result.length != 2) {

View File

@@ -48,8 +48,10 @@ import net.sourceforge.plantuml.SourceStringReader;
@SuppressWarnings("SERIAL")
public class OldProxyServlet extends HttpServlet {
/**
* Proxy request URI regex pattern.
*/
private static final Pattern PROXY_PATTERN = Pattern.compile("/\\w+/proxy/((\\d+)/)?((\\w+)/)?(https?://.*)");
private String format;
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
@@ -64,20 +66,44 @@ public class OldProxyServlet extends HttpServlet {
}
String num = proxyMatcher.group(2); // Optional number of the diagram source
format = proxyMatcher.group(4); // Expected format of the generated diagram
String format = proxyMatcher.group(4); // Expected format of the generated diagram
String sourceURL = proxyMatcher.group(5);
handleImageProxy(response, num, sourceURL);
handleImageProxy(response, num, format, sourceURL);
}
private void handleImageProxy(HttpServletResponse response, String num, String source) throws IOException {
/**
* Handle image proxy request.
*
* @param response http response
* @param num image number/index of uml {@code source}
* @param format file format name
* @param source diagram source URL
*
* @throws IOException if an input or output exception occurred
*/
private void handleImageProxy(
HttpServletResponse response,
String num,
String format,
String source
) throws IOException {
SourceStringReader reader = new SourceStringReader(getSource(source));
int n = num == null ? 0 : Integer.parseInt(num);
FileFormat fileFormat = getOutputFormat();
FileFormat fileFormat = getOutputFormat(format);
response.addHeader("Content-Type", fileFormat.getMimeType());
reader.outputImage(response.getOutputStream(), n, new FileFormatOption(fileFormat, false));
}
/**
* Get textual diagram source from URL.
*
* @param uri diagram source URL
*
* @return textual diagram source
*
* @throws IOException if an input or output exception occurred
*/
private String getSource(final String uri) throws IOException {
final URL url = new URL(uri);
try (
@@ -95,7 +121,15 @@ public class OldProxyServlet extends HttpServlet {
}
}
private FileFormat getOutputFormat() {
/**
* Get {@link FileFormat} instance from string.
*
* @param format file format name
*
* @return corresponding file format instance,
* if {@code format} is null or unknown the default {@link FileFormat#PNG} will be returned
*/
private FileFormat getOutputFormat(String format) {
if (format == null) {
return FileFormat.PNG;
}

View File

@@ -44,7 +44,7 @@ import net.sourceforge.plantuml.code.TranscoderUtil;
import net.sourceforge.plantuml.png.MetadataTag;
/**
* Original idea from Achim Abeling for Confluence macro
* Original idea from Achim Abeling for Confluence macro.
*
* This class is the old all-in-one historic implementation of the PlantUml server.
* See package.html for the new design. It's a work in progress.
@@ -56,10 +56,19 @@ import net.sourceforge.plantuml.png.MetadataTag;
@SuppressWarnings("SERIAL")
public class PlantUmlServlet extends HttpServlet {
/**
* Default encoded uml text.
* Bob -> Alice : hello
*/
private static final String DEFAULT_ENCODED_TEXT = "SyfFKj2rKt3CoKnELR1Io4ZDoSa70000";
// Last part of the URL
public static final Pattern URL_PATTERN = Pattern.compile("^.*[^a-zA-Z0-9\\-\\_]([a-zA-Z0-9\\-\\_]+)");
/**
* Regex pattern to fetch last part of the URL.
*/
private static final Pattern URL_PATTERN = Pattern.compile("^.*[^a-zA-Z0-9\\-\\_]([a-zA-Z0-9\\-\\_]+)");
/**
* Regex pattern to fetch encoded uml text from an "uml" URL.
*/
private static final Pattern RECOVER_UML_PATTERN = Pattern.compile("/uml/(.*)");
static {
@@ -134,36 +143,75 @@ public class PlantUmlServlet extends HttpServlet {
redirectNow(request, response, encoded);
}
/**
* Get textual diagram source from URL.
*
* @param request http request which contains the source URL
* @param text fallback textual diagram source
*
* @return if successful textual diagram source from URL; otherwise fallback {@code text}
*
* @throws IOException if an input or output exception occurred
*/
private String getTextFromUrl(HttpServletRequest request, String text) throws IOException {
String url = request.getParameter("url");
final Matcher recoverUml = RECOVER_UML_PATTERN.matcher(request.getRequestURI().substring(
request.getContextPath().length()));
final Matcher recoverUml = RECOVER_UML_PATTERN.matcher(
request.getRequestURI().substring(request.getContextPath().length())
);
// the URL form has been submitted
if (recoverUml.matches()) {
final String data = recoverUml.group(1);
text = getTranscoder().decode(data);
} else if (url != null && !url.trim().isEmpty()) {
// Catch the last part of the URL if necessary
final Matcher m1 = URL_PATTERN.matcher(url);
if (m1.find()) {
url = m1.group(1);
}
text = getTranscoder().decode(url);
return getTranscoder().decode(data);
}
String url = request.getParameter("url");
if (url != null && !url.trim().isEmpty()) {
// Catch the last part of the URL if necessary
final Matcher matcher = URL_PATTERN.matcher(url);
if (matcher.find()) {
url = matcher.group(1);
}
return getTranscoder().decode(url);
}
// fallback
return text;
}
private void redirectNow(HttpServletRequest request, HttpServletResponse response, String encoded)
throws IOException {
/**
* Send redirect response to encoded uml text.
*
* @param request http request
* @param response http response
* @param encoded encoded uml text
*
* @throws IOException if an input or output exception occurred
*/
private void redirectNow(
HttpServletRequest request,
HttpServletResponse response,
String encoded
) throws IOException {
final String result = request.getContextPath() + "/uml/" + encoded;
response.sendRedirect(result);
}
/**
* Get PlantUML transcoder.
*
* @return transcoder instance
*/
private Transcoder getTranscoder() {
return TranscoderUtil.getDefaultTranscoder();
}
static private HttpURLConnection getConnection(URL url) throws IOException {
/**
* Get open http connection from URL.
*
* @param url URL to open connection
*
* @return open http connection
*
* @throws IOException if an input or output exception occurred
*/
private static HttpURLConnection getConnection(URL url) throws IOException {
if (url.getProtocol().startsWith("https")) {
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
con.setRequestMethod("GET");
@@ -180,7 +228,16 @@ public class PlantUmlServlet extends HttpServlet {
}
}
static public InputStream getImage(URL url) throws IOException {
/**
* Get image input stream from URL.
*
* @param url URL to open connection
*
* @return response input stream from URL
*
* @throws IOException if an input or output exception occurred
*/
private static InputStream getImage(URL url) throws IOException {
InputStream is = null;
HttpURLConnection con = getConnection(url);
is = con.getInputStream();

View File

@@ -102,6 +102,15 @@ public class ProxyServlet extends HttpServlet {
dr = null;
}
/**
* Get textual uml diagram source from URL.
*
* @param url source URL
*
* @return textual uml diagram source
*
* @throws IOException if an input or output exception occurred
*/
private String getSource(final URL url) throws IOException {
String line;
BufferedReader rd;
@@ -124,6 +133,14 @@ public class ProxyServlet extends HttpServlet {
return "";
}
/**
* Get {@link FileFormat} instance from string.
*
* @param format file format name
*
* @return corresponding file format instance,
* if {@code format} is null or unknown the default {@link FileFormat#PNG} will be returned
*/
private FileFormat getOutputFormat(String format) {
if (format == null) {
return FileFormat.PNG;
@@ -143,6 +160,15 @@ public class ProxyServlet extends HttpServlet {
return FileFormat.PNG;
}
/**
* Get open http connection from URL.
*
* @param url URL to open connection
*
* @return open http connection
*
* @throws IOException if an input or output exception occurred
*/
private HttpURLConnection getConnection(final URL url) throws IOException {
final HttpURLConnection con = (HttpURLConnection) url.openConnection();
//if (con instanceof HttpsURLConnection) {
@@ -159,7 +185,8 @@ public class ProxyServlet extends HttpServlet {
}
/**
* Debug method used to dump the certificate info
* Debug method used to dump the certificate info.
*
* @param con the https connection
*/
@SuppressWarnings("unused")

View File

@@ -43,6 +43,11 @@ import java.util.regex.Pattern;
@SuppressWarnings("SERIAL")
public abstract class UmlDiagramService extends HttpServlet {
/**
* Regex pattern to fetch encoded uml text from an URL.
*/
private static final Pattern RECOVER_UML_PATTERN = Pattern.compile("/\\w+/(\\d+/)?(.*)");
static {
OptionFlags.ALLOW_INCLUDE = false;
if ("true".equalsIgnoreCase(System.getenv("ALLOW_PLANTUML_INCLUDE"))) {
@@ -52,7 +57,6 @@ public abstract class UmlDiagramService extends HttpServlet {
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
// build the UML source from the compressed request parameter
final String[] sourceAndIdx = getSourceAndIdx(request);
final int idx = Integer.parseInt(sourceAndIdx[1]);
@@ -70,7 +74,6 @@ public abstract class UmlDiagramService extends HttpServlet {
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
// build the UML source from the compressed request parameter
final String[] sourceAndIdx = getSourceAndIdx(request);
final int idx = Integer.parseInt(sourceAndIdx[1]);
@@ -88,13 +91,22 @@ public abstract class UmlDiagramService extends HttpServlet {
doDiagramResponse(request, response, uml.toString(), idx);
}
/**
* Send diagram response.
*
* @param request html request
* @param response html response
* @param uml textual UML diagram(s) source
* @param idx diagram index of {@code uml} to send
*
* @throws IOException if an input or output exception occurred
*/
private void doDiagramResponse(
HttpServletRequest request,
HttpServletResponse response,
String uml,
int idx)
throws IOException {
int idx
) throws IOException {
// generate the response
DiagramResponse dr = new DiagramResponse(response, getOutputFormat(), request);
try {
@@ -103,11 +115,8 @@ public abstract class UmlDiagramService extends HttpServlet {
// Browser has closed the connection, so the HTTP OutputStream is closed
// Silently catch the exception to avoid annoying log
}
dr = null;
}
private static final Pattern RECOVER_UML_PATTERN = Pattern.compile("/\\w+/(\\d+/)?(.*)");
/**
* Extracts the UML source text and its index from the HTTP request.
*
@@ -132,7 +141,7 @@ public abstract class UmlDiagramService extends HttpServlet {
return new String[]{data, idx };
}
}
return new String[]{"", "0" };
return new String[]{"", "0"};
}
/**

View File

@@ -28,13 +28,22 @@ import java.io.InputStream;
import java.util.Properties;
/**
* Shared PlantUML Server configuration.
*/
public final class Configuration {
/**
* Singleton configuration instance.
*/
private static Configuration instance;
/**
* Configuration properties.
*/
private Properties config;
/**
* Singleton constructor
* Singleton constructor.
*/
private Configuration() {
config = new Properties();
@@ -57,7 +66,7 @@ public final class Configuration {
}
/**
* Get the configuration
* Get the configuration.
*
* @return the complete configuration
*/
@@ -69,7 +78,9 @@ public final class Configuration {
}
/**
* Get a boolean configuration value
* Get a boolean configuration value.
*
* @param key config property key
*
* @return true if the value is "on"
*/

View File

@@ -26,29 +26,19 @@ package net.sourceforge.plantuml.servlet.utility;
import java.io.IOException;
import java.io.OutputStream;
/**
* This output stream ignores everything and writes nothing.
*/
public class NullOutputStream extends OutputStream {
/**
* Writes to nowhere
* Writes to nowhere.
*
* @param b anything
*/
@Override
public void write(int b) throws IOException {
// Do nothing silently
}
/**
* Overridden for performance reason
*/
@Override
public void write(byte[] b) throws IOException {
// Do nothing silently
}
/**
* Overridden for performance reason
*/
@Override
public void write(byte[] b, int off, int len) throws IOException {
// Do nothing silently
}
}

View File

@@ -35,7 +35,7 @@ import net.sourceforge.plantuml.code.TranscoderUtil;
* Utility class to extract the UML source from the compressed UML source contained in the end part
* of the requested URI.
*/
public class UmlExtractor {
public abstract class UmlExtractor {
static {
OptionFlags.ALLOW_INCLUDE = false;
@@ -49,6 +49,7 @@ public class UmlExtractor {
* HTTP URI.
*
* @param source the last part of the URI containing the compressed UML
*
* @return the textual UML source
*/
static public String getUmlSource(String source) {
@@ -83,9 +84,4 @@ public class UmlExtractor {
return uml;
}
protected UmlExtractor() {
// prevents calls from subclass
throw new UnsupportedOperationException();
}
}

View File

@@ -28,9 +28,8 @@
<link rel="icon" href="${hostpath}/favicon.ico" type="image/x-icon"/>
<link rel="shortcut icon" href="${hostpath}/favicon.ico" type="image/x-icon"/>
<link rel="stylesheet" href="${hostpath}/plantuml.css" />
<link rel="stylesheet" href="${hostpath}/webjars/codemirror/3.21/lib/codemirror.css" />
<script src="${hostpath}/webjars/codemirror/3.21/lib/codemirror.js"></script>
<!-- <script src="mode/plantuml.js"></script> -->
<link rel="stylesheet" href="${hostpath}/webjars/codemirror/5.63.0/lib/codemirror.css" />
<script src="${hostpath}/webjars/codemirror/5.63.0/lib/codemirror.js"></script>
<script>
window.onload = function() {
document.myCodeMirror = CodeMirror.fromTextArea(

View File

@@ -6,16 +6,16 @@ package net.sourceforge.plantuml.servlet;
*/
public abstract class TestUtils {
/*
* Theses strings are the compressed form of a PlantUML diagram.
*/
//
// Theses strings are the compressed form of a PlantUML diagram.
//
/*
/**
* version
*/
public static final String VERSION = "AqijAixCpmC0";
/*
/**
* Bob -> Alice : hello
*/
public static final String SEQBOB = "SyfFKj2rKt3CoKnELR1Io4ZDoSa70000";