Compare commits
253 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
da7e041070 | ||
|
2680086893 | ||
|
eafc9c442c | ||
|
8c532d4caa | ||
|
bba12d9c3c | ||
|
449e4d8ae4 | ||
|
861b034ebc | ||
|
334f039e90 | ||
|
c127b4c466 | ||
|
74eb159a36 | ||
|
0514103cc1 | ||
|
46077bf5b7 | ||
|
608b58b3e0 | ||
|
5859c3b427 | ||
|
af8f7d0c33 | ||
|
d495c13e6e | ||
|
e484f532d4 | ||
|
f03bb68407 | ||
|
294b2a2418 | ||
|
45994f81bf | ||
|
4202730c11 | ||
|
09a7ce4973 | ||
|
5fa6cbc82f | ||
|
178384370f | ||
|
8d7c681ae4 | ||
|
98dfd1763a | ||
|
f6fa448ed8 | ||
|
303976279f | ||
|
be95ece466 | ||
|
4cbefc3dcc | ||
|
155250286f | ||
|
478ef3bce7 | ||
|
080cbaada9 | ||
|
6c2bae2f8a | ||
|
6ca582fcb7 | ||
|
ec7b9f9b1a | ||
|
09517cca92 | ||
|
6538be2047 | ||
|
a6e69b33eb | ||
|
f0d78a146b | ||
|
5d7c4e1a03 | ||
|
323aad1525 | ||
|
e5d11fb89a | ||
|
e6566b58bd | ||
|
ed49010303 | ||
|
f727c6dd13 | ||
|
763976abdd | ||
|
3ef176edae | ||
|
385fa1274a | ||
|
972d136665 | ||
|
329aae7fc6 | ||
|
ebece93726 | ||
|
8a9825395a | ||
|
df081c20a4 | ||
|
4137d8460e | ||
|
a627da7a1a | ||
|
a9bd29a91d | ||
|
638724925e | ||
|
1245b15e01 | ||
|
99f85c0c9b | ||
|
4a5e204e16 | ||
|
8cb5ca0daf | ||
|
afd8bbcceb | ||
|
6d90304fd7 | ||
|
f62ba44e7d | ||
|
823b506900 | ||
|
b458bfad19 | ||
|
a7a5b91933 | ||
|
20468f5bd9 | ||
|
10dd88714a | ||
|
df9c10604a | ||
|
0154160c7d | ||
|
4d65def8bb | ||
|
efd53664f2 | ||
|
345e996673 | ||
|
dcd4436fcf | ||
|
7285ce1cc8 | ||
|
a0ed47b51c | ||
|
052a7ea96f | ||
|
b8cb1e2ff0 | ||
|
cf717eff0c | ||
|
820fcca9ac | ||
|
2d011e233e | ||
|
dcc06f9afc | ||
|
4c76f0389d | ||
|
dd028e9579 | ||
|
94678b720e | ||
|
b5c21c76b6 | ||
|
ca3e9312b3 | ||
|
ba6af87b2d | ||
|
249163e149 | ||
|
0330b7c4a2 | ||
|
cebca916fe | ||
|
d5ef062af4 | ||
|
74f35846a7 | ||
|
e83dfa2b3a | ||
|
8c45a7b106 | ||
|
f14337933d | ||
|
c94711c2d5 | ||
|
b995dcdb61 | ||
|
494dfba063 | ||
|
c8954cbe4a | ||
|
5e0ccaf328 | ||
|
86bb70d079 | ||
|
da290a15fe | ||
|
12224aa16e | ||
|
c5f088e50a | ||
|
54016d325d | ||
|
7b0022de44 | ||
|
32e05b62bd | ||
|
e5cb82ef2c | ||
|
7c578c482f | ||
|
422ebe1792 | ||
|
67fbe35fc3 | ||
|
807ca66fe1 | ||
|
d99366a33d | ||
|
1580aa2b6f | ||
|
aea068abed | ||
|
3763ee737e | ||
|
db31315485 | ||
|
9cb9cec6ca | ||
|
b1b7dfb84b | ||
|
deda3c2256 | ||
|
098e630a28 | ||
|
8d5be87f03 | ||
|
221af78afc | ||
|
5190a72cc8 | ||
|
a7789025eb | ||
|
61cbf1d3e5 | ||
|
eee8ca6084 | ||
|
f4c55bb171 | ||
|
eb38f39419 | ||
|
285d5ebfdf | ||
|
6487acdde0 | ||
|
32b8d60bf1 | ||
|
6cb587e156 | ||
|
755b62c885 | ||
|
c92c4de36a | ||
|
3c217b2de1 | ||
|
f08db467c8 | ||
|
d4d00ca79e | ||
|
04af2a25d2 | ||
|
eae269348f | ||
|
c4cec58783 | ||
|
ac05a3c8c5 | ||
|
aba539f62d | ||
|
2f8bd087b8 | ||
|
a94ab06493 | ||
|
6839b93ac2 | ||
|
69f55398cb | ||
|
51b4286467 | ||
|
a87a198725 | ||
|
934a0edc52 | ||
|
8805b90913 | ||
|
1a02835f8f | ||
|
f4f6ca5773 | ||
|
3c6b8da0ff | ||
|
e2e1c915a6 | ||
|
bde7ee5683 | ||
|
5aa3b56840 | ||
|
d53fb43ac4 | ||
|
d6dcdab421 | ||
|
655f53fc28 | ||
|
4f7b56e80b | ||
|
af01537429 | ||
|
92e88f3fa4 | ||
|
4433e6cc1b | ||
|
35af5917e7 | ||
|
2f18333605 | ||
|
f355dc6666 | ||
|
36ccc2f25c | ||
|
ba6081902b | ||
|
5da0a51e9d | ||
|
51e0922eea | ||
|
448c8f614f | ||
|
de48bbe463 | ||
|
1d6155fc8e | ||
|
bbed9612ea | ||
|
5bfbf72262 | ||
|
95426c8d14 | ||
|
e9dfb036fc | ||
|
af041744ee | ||
|
49c8fefce5 | ||
|
de6612091c | ||
|
37a96a29c4 | ||
|
9bc56edca6 | ||
|
83138142c5 | ||
|
aa9172f715 | ||
|
a985880361 | ||
|
18d887385f | ||
|
b7651c4dae | ||
|
894be6744e | ||
|
b98e227ce7 | ||
|
d73b61a805 | ||
|
513453e51b | ||
|
10707c4df7 | ||
|
749cdfb7ab | ||
|
eedd4691c8 | ||
|
5e7b8ddad0 | ||
|
fffa69238c | ||
|
7112ea8a04 | ||
|
2b4fbe2452 | ||
|
e98937d0b3 | ||
|
ea7bb65d4e | ||
|
887a5055f2 | ||
|
cd65d5719a | ||
|
a53416b4da | ||
|
b9df1f2278 | ||
|
e276733481 | ||
|
3c3c64b3d6 | ||
|
73739b7e85 | ||
|
f5d9b2591f | ||
|
7eba9632e6 | ||
|
f878c0ec22 | ||
|
60b716d61b | ||
|
978a203487 | ||
|
1b07c6d9c2 | ||
|
0ec8cb68f4 | ||
|
c5e0c6fdea | ||
|
c4ace921cd | ||
|
bd49d5cf7f | ||
|
1398d778bb | ||
|
18d461a38a | ||
|
74db037a27 | ||
|
813500c549 | ||
|
44487018ce | ||
|
731ea2ff87 | ||
|
73c23724db | ||
|
38772dedd3 | ||
|
5501258087 | ||
|
c30807b178 | ||
|
59f37e996d | ||
|
055facac9e | ||
|
3ce59edba7 | ||
|
31a42da6bb | ||
|
d73dea3d58 | ||
|
f0b05ab711 | ||
|
401659a4a2 | ||
|
dcc38976b9 | ||
|
2b1deed9dd | ||
|
902241954f | ||
|
b340965ef9 | ||
|
3920af3a91 | ||
|
b9b9864ccc | ||
|
f26038fc4c | ||
|
fc730f24fc | ||
|
cb2cb80931 | ||
|
5ef45f643d | ||
|
ad09f193f4 | ||
|
fe305e01da | ||
|
263bbf59da | ||
|
7ad8b8033d | ||
|
353b089904 |
3
.dockerignore
Normal file
|
@ -0,0 +1,3 @@
|
|||
# .dockerignore -- stuff we don't need during image builds
|
||||
|
||||
/.git/
|
25
.editorconfig
Normal file
|
@ -0,0 +1,25 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.java]
|
||||
indent_size = 4
|
||||
|
||||
[*.md]
|
||||
max_line_length = off
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.puml]
|
||||
insert_final_newline = false
|
||||
|
||||
[{Dockerfile,Dockerfile.*}]
|
||||
indent_size = 4
|
||||
|
||||
[.vscode/*.json]
|
||||
indent_size = 4
|
1
.gitattributes
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
* text=auto eol=lf
|
5
.github/FUNDING.yml
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
# These are supported funding model platforms
|
||||
|
||||
github: plantuml
|
||||
patreon: plantuml
|
||||
liberapay: plantuml
|
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
|
||||
- OS: [e.g. iOS]
|
||||
- Browser [e.g. chrome, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Smartphone (please complete the following information):**
|
||||
|
||||
- Device: [e.g. iPhone6]
|
||||
- OS: [e.g. iOS8.1]
|
||||
- Browser [e.g. stock browser, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
27
.github/ISSUE_TEMPLATE/documentation_request.md
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
---
|
||||
name: Documentation request
|
||||
about: Identify an area for improvement in documentation
|
||||
|
||||
---
|
||||
|
||||
**What is the URL of the documentation?**
|
||||
|
||||
- **Example:** https://github.com/evantill/docker-cheerpj/blob/main/README.md#example-of-using-cheerpj-on-your-computer
|
||||
|
||||
- *Note:* This URL includes the web page and the section of the documentation.
|
||||
|
||||
**What can be improved?**
|
||||
|
||||
A clear and concise description of what can be improved.
|
||||
Examples:
|
||||
|
||||
- "I don't understand where the ${XYZ} variable is set."
|
||||
- "There seems to be a step missing between 'X' and 'Z'. I don't know how to get to 'Z'."
|
||||
- "When I run `command sub-command ...` I get the following error:"
|
||||
- "I don't know what is meant by 'gerble barb gazoink` in the instructions".
|
||||
|
||||
**Additional context**
|
||||
|
||||
Add any other context or screenshots to help describe the documentation improvement.
|
||||
If you think the documentation improvement is operating system specific,
|
||||
please indicate which operating system is being used.
|
17
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
207
.github/workflows/main.yml
vendored
Normal file
|
@ -0,0 +1,207 @@
|
|||
name: Main
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
|
||||
jobs:
|
||||
build-jdk11:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: "zulu"
|
||||
java-version: 11
|
||||
check-latest: true
|
||||
cache: "maven"
|
||||
|
||||
- name: get tag name
|
||||
id: version
|
||||
run: echo "VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: build with maven
|
||||
run: mvn --batch-mode --define java.net.useSystemProxies=true package
|
||||
|
||||
- name: create renamed build
|
||||
run: cp target/plantuml.war target/plantuml-${{ steps.version.outputs.VERSION }}.war
|
||||
|
||||
- name: build with maven (including the apache-jsp artifact)
|
||||
run: mvn --batch-mode --define java.net.useSystemProxies=true -Dapache-jsp.scope=compile package
|
||||
|
||||
- name: create renamed build (including the apache-jsp artifact)
|
||||
run: cp target/plantuml.war target/plantuml-jsp-${{ steps.version.outputs.VERSION }}.war
|
||||
|
||||
- name: temporarily save generated war files
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: war-jre11
|
||||
path: target/plantuml*-${{ steps.version.outputs.VERSION }}.war
|
||||
|
||||
build-jdk8:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: "zulu"
|
||||
java-version: 8
|
||||
check-latest: true
|
||||
cache: "maven"
|
||||
|
||||
- name: get tag name
|
||||
id: version
|
||||
run: echo "VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Remove test code (not java 8 compatible)
|
||||
run: rm -rf src/test
|
||||
|
||||
- name: build with maven
|
||||
run: mvn --batch-mode -f pom.jdk8.xml --define java.net.useSystemProxies=true package
|
||||
|
||||
- name: create renamed build
|
||||
run: cp target/plantuml.war target/plantuml-jre8-${{ steps.version.outputs.VERSION }}.war
|
||||
|
||||
- name: build with maven (including the apache-jsp artifact)
|
||||
run: mvn --batch-mode -f pom.jdk8.xml --define java.net.useSystemProxies=true -Dapache-jsp.scope=compile package
|
||||
|
||||
- name: create renamed build (including the apache-jsp artifact)
|
||||
run: cp target/plantuml.war target/plantuml-jre8-jsp-${{ steps.version.outputs.VERSION }}.war
|
||||
|
||||
- name: temporarily save generated war files
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: war-jre8
|
||||
path: target/plantuml*-${{ steps.version.outputs.VERSION }}.war
|
||||
|
||||
publish-releases:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- build-jdk11
|
||||
- build-jdk8
|
||||
steps:
|
||||
- name: retrieve generated war files (jre8)
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: war-jre8
|
||||
path: artifacts
|
||||
|
||||
- name: retrieve generated war files (jre11)
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: war-jre11
|
||||
path: artifacts
|
||||
|
||||
- name: display structure of downloaded files
|
||||
run: ls -lah artifacts
|
||||
|
||||
- name: upload binaries to release
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: artifacts/plantuml*.war
|
||||
tag: ${{ github.ref }}
|
||||
overwrite: true
|
||||
file_glob: true
|
||||
|
||||
publish-docker:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- publish-releases
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Docker tomcat meta
|
||||
id: docker_meta_tomcat
|
||||
uses: crazy-max/ghaction-docker-meta@v3
|
||||
with:
|
||||
flavor: |
|
||||
latest=false
|
||||
prefix=
|
||||
suffix=
|
||||
images: plantuml/plantuml-server
|
||||
tags: |
|
||||
type=semver,pattern=tomcat-{{raw}}
|
||||
type=raw,value=tomcat
|
||||
|
||||
- name: Docker jetty meta
|
||||
id: docker_meta_jetty
|
||||
uses: crazy-max/ghaction-docker-meta@v3
|
||||
with:
|
||||
flavor: |
|
||||
latest=true
|
||||
prefix=
|
||||
suffix=
|
||||
images: plantuml/plantuml-server
|
||||
tags: |
|
||||
type=semver,pattern={{raw}}
|
||||
type=semver,pattern=jetty-{{raw}}
|
||||
type=raw,value=jetty
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Build & push tomcat
|
||||
id: docker_build_tomcat
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile.tomcat
|
||||
platforms: linux/amd64, linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.docker_meta_tomcat.outputs.tags }}
|
||||
labels: ${{ steps.docker_meta_tomcat.outputs.labels }}
|
||||
|
||||
- name: Build & push jetty
|
||||
id: docker_build_jetty
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile.jetty
|
||||
platforms: linux/amd64, linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.docker_meta_jetty.outputs.tags }}
|
||||
labels: ${{ steps.docker_meta_jetty.outputs.labels }}
|
||||
|
||||
publish-pages:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- publish-releases
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: "zulu"
|
||||
java-version: 11
|
||||
check-latest: true
|
||||
cache: "maven"
|
||||
|
||||
- name: Create GitHub Pages
|
||||
run: mvn site
|
||||
|
||||
- name: Deploy GitHub Pages
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: ./target/site
|
258
.github/workflows/tests.yml
vendored
Normal file
|
@ -0,0 +1,258 @@
|
|||
name: Tests
|
||||
|
||||
on:
|
||||
- push
|
||||
- pull_request
|
||||
|
||||
jobs:
|
||||
test-java-8-war-generation:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: "zulu"
|
||||
java-version: 8
|
||||
check-latest: true
|
||||
cache: "maven"
|
||||
|
||||
- name: Remove test code (not java 8 compatible)
|
||||
run: rm -rf src/test
|
||||
|
||||
- name: Generate war file (including apache-jsp artifact)
|
||||
run: mvn --batch-mode -f pom.jdk8.xml -D java.net.useSystemProxies=true -Dapache-jsp.scope=compile clean package
|
||||
|
||||
- name: Generate war file
|
||||
run: mvn --batch-mode -f pom.jdk8.xml -D java.net.useSystemProxies=true clean package
|
||||
|
||||
- name: temporarily save generated files
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: war-jre8
|
||||
path: target/plantuml.war
|
||||
retention-days: 1
|
||||
|
||||
test-java-8-war:
|
||||
runs-on: ubuntu-latest
|
||||
needs: test-java-8-war-generation
|
||||
strategy:
|
||||
matrix:
|
||||
java-version: [ 11, 17 ]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: retrieve generated files (jre8)
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: war-jre8
|
||||
path: artifacts
|
||||
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: "zulu"
|
||||
java-version: ${{ matrix.java-version }}
|
||||
check-latest: true
|
||||
cache: "maven"
|
||||
|
||||
- name: Prepare jetty-runner tests
|
||||
run: mvn --batch-mode clean package
|
||||
|
||||
- name: Start jetty server over jetty-runner
|
||||
run: java -jar target/dependency/jetty-runner.jar --config src/main/config/jetty.xml --path /plantuml artifacts/plantuml.war &
|
||||
|
||||
- name: Wait 5 seconds (to let jetty-runner start the jetty server)
|
||||
run: sleep 5s
|
||||
|
||||
- name: Run tests against "mvn jetty:run" server
|
||||
run: mvn --batch-mode test -DskipTests=false -Dgroups=\!graphviz-test -DargLine="-Dsystem.test.server=http://localhost:8080/plantuml"
|
||||
|
||||
test-mvn-livecycle:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
java-version: [ 11, 17 ]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: "zulu"
|
||||
java-version: ${{ matrix.java-version }}
|
||||
check-latest: true
|
||||
cache: "maven"
|
||||
|
||||
- name: Lifecycle - Step 1/8 - mvn clean
|
||||
run: mvn --batch-mode clean
|
||||
|
||||
- name: Lifecycle - Step 2/8 - mvn validate
|
||||
run: mvn --batch-mode validate
|
||||
|
||||
- name: Lifecycle - Step 3/8 - mvn compile
|
||||
run: mvn --batch-mode compile
|
||||
|
||||
- name: Lifecycle - Step 4/8 - mvn test (with skipTests=true)
|
||||
run: mvn --batch-mode test
|
||||
|
||||
- name: Lifecycle - Step 5/8 - mvn package
|
||||
run: mvn --batch-mode package
|
||||
|
||||
- name: Lifecycle - Step 6/8 - mvn verify
|
||||
run: mvn --batch-mode verify
|
||||
|
||||
- name: Lifecycle - Step 7/8 - mvn install
|
||||
run: mvn --batch-mode install
|
||||
|
||||
- name: Lifecycle - Step 8/8 - mvn site
|
||||
run: mvn --batch-mode site
|
||||
|
||||
test-embedded:
|
||||
runs-on: ubuntu-latest
|
||||
needs: test-mvn-livecycle
|
||||
strategy:
|
||||
matrix:
|
||||
java-version: [ 11, 17 ]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: "zulu"
|
||||
java-version: ${{ matrix.java-version }}
|
||||
check-latest: true
|
||||
cache: "maven"
|
||||
|
||||
- name: Run tests against jetty embedded server
|
||||
run: mvn --batch-mode clean test -DskipTests=false -Dgroups=\!graphviz-test
|
||||
|
||||
test-mvn-jetty-run:
|
||||
runs-on: ubuntu-latest
|
||||
needs: test-mvn-livecycle
|
||||
strategy:
|
||||
matrix:
|
||||
java-version: [ 11, 17 ]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: "zulu"
|
||||
java-version: ${{ matrix.java-version }}
|
||||
check-latest: true
|
||||
cache: "maven"
|
||||
|
||||
- name: Prepare "mvn jetty:run" tests
|
||||
run: mvn --batch-mode clean test
|
||||
|
||||
- name: Start jetty server over maven
|
||||
run: mvn --batch-mode jetty:run &
|
||||
|
||||
- name: Wait 20 seconds (to let maven start the jetty server)
|
||||
run: sleep 20s
|
||||
|
||||
- name: Run tests against "mvn jetty:run" server
|
||||
run: mvn --batch-mode test -DskipTests=false -Dgroups=\!graphviz-test -DargLine="-Dsystem.test.server=http://localhost:8080/plantuml"
|
||||
|
||||
test-jetty-runner:
|
||||
runs-on: ubuntu-latest
|
||||
needs: test-mvn-livecycle
|
||||
strategy:
|
||||
matrix:
|
||||
java-version: [ 11, 17 ]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: "zulu"
|
||||
java-version: ${{ matrix.java-version }}
|
||||
check-latest: true
|
||||
cache: "maven"
|
||||
|
||||
- name: Prepare jetty-runner tests
|
||||
run: mvn --batch-mode clean package
|
||||
|
||||
- name: Start jetty server over jetty-runner
|
||||
run: java -jar target/dependency/jetty-runner.jar --config src/main/config/jetty.xml --path /plantuml target/plantuml.war &
|
||||
|
||||
- name: Wait 5 seconds (to let jetty-runner start the jetty server)
|
||||
run: sleep 5s
|
||||
|
||||
- name: Run tests against "mvn jetty:run" server
|
||||
run: mvn --batch-mode test -DskipTests=false -Dgroups=\!graphviz-test -DargLine="-Dsystem.test.server=http://localhost:8080/plantuml"
|
||||
|
||||
test-jetty:
|
||||
runs-on: ubuntu-latest
|
||||
needs: test-mvn-livecycle
|
||||
strategy:
|
||||
matrix:
|
||||
java-version: [ 11, 17 ]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: "zulu"
|
||||
java-version: ${{ matrix.java-version }}
|
||||
check-latest: true
|
||||
cache: "maven"
|
||||
|
||||
- name: Prepare external tests
|
||||
run: mvn --batch-mode clean test
|
||||
|
||||
- name: Build the jetty docker stack
|
||||
run: |
|
||||
docker image build -f Dockerfile.jetty -t plantuml-server:local .
|
||||
docker run -d --hostname=test.localhost -p 8080:8080 -e BASE_URL=plantuml plantuml-server:local
|
||||
|
||||
- name: Check running containers
|
||||
run: docker ps
|
||||
|
||||
- name: run tests against jetty docker image
|
||||
run: mvn --batch-mode test -DskipTests=false -DargLine="-Dsystem.test.server=http://localhost:8080/plantuml"
|
||||
|
||||
test-tomcat:
|
||||
runs-on: ubuntu-latest
|
||||
needs: test-mvn-livecycle
|
||||
strategy:
|
||||
matrix:
|
||||
java-version: [ 11, 17 ]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: "zulu"
|
||||
java-version: ${{ matrix.java-version }}
|
||||
check-latest: true
|
||||
cache: "maven"
|
||||
|
||||
- name: Prepare external tests
|
||||
run: mvn --batch-mode clean test
|
||||
|
||||
- name: Build the tomcat docker stack
|
||||
run: |
|
||||
docker image build -f Dockerfile.tomcat -t plantuml-server:local .
|
||||
docker run -d --hostname=test.localhost -p 8080:8080 -e BASE_URL=plantuml plantuml-server:local
|
||||
|
||||
- name: Check running containers
|
||||
run: docker ps
|
||||
|
||||
- name: run tests against tomcat docker image
|
||||
run: mvn --batch-mode test -DskipTests=false -DargLine="-Dsystem.test.server=http://localhost:8080/plantuml"
|
8
.gitignore
vendored
|
@ -1,5 +1,13 @@
|
|||
# Eclipse Ignores
|
||||
target
|
||||
.settings
|
||||
.classpath
|
||||
.project
|
||||
.checkstyle
|
||||
|
||||
# IntelliJ ignores
|
||||
.idea/
|
||||
out/
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
23
.travis.yml
|
@ -1,23 +0,0 @@
|
|||
language: java
|
||||
|
||||
sudo: required
|
||||
|
||||
services:
|
||||
- docker
|
||||
|
||||
after_success:
|
||||
- docker login -u $DOCKER_LOGIN -p $DOCKER_PASSWORD
|
||||
- if [ "$TRAVIS_BRANCH" == "master" ]; then
|
||||
|
||||
docker build --pull -t plantuml/plantuml-server:jetty -f Dockerfile.jetty . ;
|
||||
docker build --pull -t plantuml/plantuml-server:tomcat -f Dockerfile.tomcat . ;
|
||||
docker tag plantuml/plantuml-server:jetty plantuml/plantuml-server:latest ;
|
||||
|
||||
docker push plantuml/plantuml-server:tomcat;
|
||||
docker push plantuml/plantuml-server:jetty;
|
||||
docker push plantuml/plantuml-server:latest;
|
||||
|
||||
docker build --pull -t plantuml/plantuml-server:armv8a -f Dockerfile.armv8a . ;
|
||||
docker push plantuml/plantuml-server:armv8a;
|
||||
|
||||
fi
|
30
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"java.configuration.updateBuildConfiguration": "automatic",
|
||||
"cSpell.words": [
|
||||
"Arnaud",
|
||||
"buildx",
|
||||
"ditaa",
|
||||
"endditaa",
|
||||
"enduml",
|
||||
"epstext",
|
||||
"etag",
|
||||
"ghaction",
|
||||
"inmemory",
|
||||
"Lalloni",
|
||||
"monaco",
|
||||
"plantuml",
|
||||
"puml",
|
||||
"Roques",
|
||||
"servlet",
|
||||
"servlets",
|
||||
"startditaa",
|
||||
"startuml",
|
||||
"undock",
|
||||
"utxt"
|
||||
],
|
||||
"cSpell.allowCompoundWords": true,
|
||||
"svg.preview.background": "dark-transparent",
|
||||
"files.associations": {
|
||||
"*.jspf": "html"
|
||||
}
|
||||
}
|
8
COPYING
|
@ -1,7 +1,7 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
@ -645,7 +645,7 @@ the "copyright" line and a pointer to where the full notice is found.
|
|||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
|
@ -664,11 +664,11 @@ might be different; for a GUI interface, you would use an "about box".
|
|||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||
|
|
20
Dockerfile
|
@ -1,20 +0,0 @@
|
|||
FROM maven:3-jdk-8
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends graphviz fonts-wqy-zenhei && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY pom.xml /app/
|
||||
COPY src /app/src/
|
||||
|
||||
ENV MAVEN_CONFIG=/app/.m2
|
||||
WORKDIR /app
|
||||
RUN mvn package
|
||||
|
||||
# chmod required to ensure any user can run the app
|
||||
RUN mkdir /app/.m2 && chmod -R a+w /app
|
||||
EXPOSE 8080
|
||||
ENV HOME /app
|
||||
|
||||
CMD java -Djetty.contextpath=/ -jar target/dependency/jetty-runner.jar target/plantuml.war
|
||||
|
||||
# To run with debugging enabled instead
|
||||
#CMD java -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -Dorg.eclipse.jetty.LEVEL=DEBUG -Djetty.contextpath=/ -jar target/dependency/jetty-runner.jar target/plantuml.war
|
|
@ -1,20 +0,0 @@
|
|||
FROM arm64v8/ubuntu:16.04
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends maven openjdk-8-jdk graphviz fonts-wqy-zenhei && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY pom.xml /app/
|
||||
COPY src /app/src/
|
||||
|
||||
ENV MAVEN_CONFIG=/app/.m2
|
||||
WORKDIR /app
|
||||
RUN mvn package
|
||||
|
||||
# chmod required to ensure any user can run the app
|
||||
RUN mkdir /app/.m2 && chmod -R a+w /app
|
||||
EXPOSE 8080
|
||||
ENV HOME /app
|
||||
|
||||
CMD java -Djetty.contextpath=/ -jar target/dependency/jetty-runner.jar target/plantuml.war
|
||||
|
||||
# To run with debugging enabled instead
|
||||
#CMD java -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -Dorg.eclipse.jetty.LEVEL=DEBUG -Djetty.contextpath=/ -jar target/dependency/jetty-runner.jar target/plantuml.war
|
|
@ -1,29 +1,79 @@
|
|||
FROM maven:3-jdk-8 AS builder
|
||||
FROM maven:3-eclipse-temurin-17 AS builder
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends graphviz fonts-wqy-zenhei && \
|
||||
apt-get clean
|
||||
COPY pom.xml pom.parent.xml /app/
|
||||
COPY src/main /app/src/main/
|
||||
|
||||
COPY pom.xml /app/
|
||||
COPY src /app/src/
|
||||
|
||||
ENV MAVEN_CONFIG=/app/.m2
|
||||
WORKDIR /app
|
||||
RUN mvn package
|
||||
RUN mvn --batch-mode --define java.net.useSystemProxies=true package
|
||||
|
||||
########################################################################################
|
||||
|
||||
FROM jetty
|
||||
MAINTAINER D.Ducatel
|
||||
FROM jetty:11.0.18-jre17-eclipse-temurin
|
||||
|
||||
# Proxy and OldProxy need empty path segments support in URIs
|
||||
# Hence: allow AMBIGUOUS_EMPTY_SEGMENT
|
||||
# Changes are only active if `/generate-jetty-start.sh` is called!
|
||||
RUN sed -i 's/# jetty\.httpConfig\.uriCompliance=DEFAULT/jetty.httpConfig.uriCompliance=DEFAULT,AMBIGUOUS_EMPTY_SEGMENT/g' /var/lib/jetty/start.d/server.ini
|
||||
|
||||
USER root
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends graphviz fonts-wqy-zenhei && \
|
||||
apt-get clean
|
||||
apt-get install -y --no-install-recommends \
|
||||
curl \
|
||||
fonts-noto-cjk \
|
||||
libgd3 \
|
||||
&& \
|
||||
rm -rf /var/lib/apt/lists/* && \
|
||||
/generate-jetty-start.sh
|
||||
|
||||
# Build Graphviz from source because there are no binary distributions for recent versions
|
||||
ARG GRAPHVIZ_VERSION
|
||||
ARG GRAPHVIZ_BUILD_DIR=/tmp/graphiz-build
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
build-essential \
|
||||
jq \
|
||||
libexpat1-dev \
|
||||
libgd-dev \
|
||||
zlib1g-dev \
|
||||
&& \
|
||||
mkdir -p $GRAPHVIZ_BUILD_DIR && \
|
||||
cd $GRAPHVIZ_BUILD_DIR && \
|
||||
GRAPHVIZ_VERSION=${GRAPHVIZ_VERSION:-$(curl -s https://gitlab.com/api/v4/projects/4207231/releases/ | jq -r '.[] | .name' | sort -V -r | head -1)} && \
|
||||
curl -o graphviz.tar.gz https://gitlab.com/api/v4/projects/4207231/packages/generic/graphviz-releases/${GRAPHVIZ_VERSION}/graphviz-${GRAPHVIZ_VERSION}.tar.gz && \
|
||||
tar -xzf graphviz.tar.gz && \
|
||||
cd graphviz-$GRAPHVIZ_VERSION && \
|
||||
./configure && \
|
||||
make && \
|
||||
make install && \
|
||||
apt-get remove -y \
|
||||
build-essential \
|
||||
jq \
|
||||
libexpat1-dev \
|
||||
libgd-dev \
|
||||
zlib1g-dev \
|
||||
&& \
|
||||
apt-get autoremove -y && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/* && \
|
||||
rm -rf $GRAPHVIZ_BUILD_DIR
|
||||
|
||||
COPY docker-entrypoint.jetty.sh /entrypoint.sh
|
||||
RUN chmod +x /entrypoint.sh
|
||||
|
||||
USER jetty
|
||||
|
||||
COPY --from=builder /app/target/plantuml.war /var/lib/jetty/webapps/ROOT.war
|
||||
ENV WEBAPP_PATH=$JETTY_BASE/webapps
|
||||
RUN rm -rf $WEBAPP_PATH && \
|
||||
mkdir -p $WEBAPP_PATH
|
||||
COPY --from=builder /app/target/plantuml.war /plantuml.war
|
||||
COPY ROOT.jetty.xml $WEBAPP_PATH/ROOT.xml
|
||||
|
||||
# Openshift https://docs.openshift.com/container-platform/4.9/openshift_images/create-images.html#images-create-guide-openshift_create-images
|
||||
USER root
|
||||
RUN chgrp -R 0 $JETTY_BASE && chmod -R g=u $JETTY_BASE
|
||||
RUN chgrp -R 0 /tmp && chmod -R g=u /tmp
|
||||
USER jetty
|
||||
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
VOLUME ["/tmp/jetty"]
|
||||
|
|
76
Dockerfile.jetty-alpine
Normal file
|
@ -0,0 +1,76 @@
|
|||
FROM maven:3-eclipse-temurin-17-alpine AS builder
|
||||
|
||||
COPY pom.xml pom.parent.xml /app/
|
||||
COPY src/main /app/src/main/
|
||||
|
||||
WORKDIR /app
|
||||
RUN mvn --batch-mode --define java.net.useSystemProxies=true package
|
||||
|
||||
########################################################################################
|
||||
|
||||
FROM jetty:11.0.18-jre17-alpine-eclipse-temurin
|
||||
|
||||
# Proxy and OldProxy need empty path segments support in URIs
|
||||
# Hence: allow AMBIGUOUS_EMPTY_SEGMENT
|
||||
# Changes are only active if `/generate-jetty-start.sh` is called!
|
||||
RUN sed -i 's/# jetty\.httpConfig\.uriCompliance=DEFAULT/jetty.httpConfig.uriCompliance=DEFAULT,AMBIGUOUS_EMPTY_SEGMENT/g' /var/lib/jetty/start.d/server.ini
|
||||
|
||||
USER root
|
||||
|
||||
RUN apk add --no-cache \
|
||||
curl \
|
||||
font-noto-cjk \
|
||||
libgd \
|
||||
&& \
|
||||
/generate-jetty-start.sh
|
||||
|
||||
#RUN apk add --no-cache graphviz
|
||||
ARG GRAPHVIZ_VERSION
|
||||
ARG GRAPHVIZ_BUILD_DIR=/tmp/graphiz-build
|
||||
RUN apk add --no-cache \
|
||||
g++ \
|
||||
jq \
|
||||
expat-dev \
|
||||
make \
|
||||
zlib \
|
||||
pkgconf \
|
||||
&& \
|
||||
mkdir -p $GRAPHVIZ_BUILD_DIR && \
|
||||
cd $GRAPHVIZ_BUILD_DIR && \
|
||||
GRAPHVIZ_VERSION=${GRAPHVIZ_VERSION:-$(curl -s https://gitlab.com/api/v4/projects/4207231/releases/ | jq -r '.[] | .name' | sort -V -r | head -1)} && \
|
||||
curl -o graphviz.tar.gz https://gitlab.com/api/v4/projects/4207231/packages/generic/graphviz-releases/${GRAPHVIZ_VERSION}/graphviz-${GRAPHVIZ_VERSION}.tar.gz && \
|
||||
tar -xzf graphviz.tar.gz && \
|
||||
cd graphviz-$GRAPHVIZ_VERSION && \
|
||||
./configure && \
|
||||
make && \
|
||||
make install && \
|
||||
apk del --no-cache \
|
||||
g++ \
|
||||
jq \
|
||||
expat-dev \
|
||||
make \
|
||||
zlib \
|
||||
&& \
|
||||
rm -rf $GRAPHVIZ_BUILD_DIR
|
||||
|
||||
COPY docker-entrypoint.jetty.sh /entrypoint.sh
|
||||
RUN chmod +x /entrypoint.sh
|
||||
|
||||
USER jetty
|
||||
|
||||
ENV WEBAPP_PATH=$JETTY_BASE/webapps
|
||||
RUN rm -rf $WEBAPP_PATH && \
|
||||
mkdir -p $WEBAPP_PATH
|
||||
COPY --from=builder /app/target/plantuml.war /plantuml.war
|
||||
COPY ROOT.jetty.xml $WEBAPP_PATH/ROOT.xml
|
||||
|
||||
# Openshift https://docs.openshift.com/container-platform/4.9/openshift_images/create-images.html#images-create-guide-openshift_create-images
|
||||
USER root
|
||||
RUN chgrp -R 0 $JETTY_BASE && \
|
||||
chmod -R g=u $JETTY_BASE
|
||||
RUN chgrp -R 0 /tmp && \
|
||||
chmod -R g=u /tmp
|
||||
USER jetty
|
||||
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
VOLUME ["/tmp/jetty"]
|
|
@ -1,24 +1,65 @@
|
|||
FROM maven:3-jdk-8 AS builder
|
||||
FROM maven:3-eclipse-temurin-11 AS builder
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends graphviz fonts-wqy-zenhei && \
|
||||
apt-get clean
|
||||
COPY pom.xml pom.parent.xml /app/
|
||||
COPY src/main /app/src/main/
|
||||
|
||||
COPY pom.xml /app/
|
||||
COPY src /app/src/
|
||||
|
||||
ENV MAVEN_CONFIG=/app/.m2
|
||||
WORKDIR /app
|
||||
RUN mvn package
|
||||
RUN mvn --batch-mode --define java.net.useSystemProxies=true -Dapache-jsp.scope=compile package
|
||||
|
||||
########################################################################################
|
||||
|
||||
FROM tomcat:9
|
||||
MAINTAINER D.Ducatel
|
||||
FROM tomcat:10-jdk11
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends graphviz fonts-wqy-zenhei && \
|
||||
apt-get clean
|
||||
apt-get install -y --no-install-recommends \
|
||||
curl \
|
||||
fonts-noto-cjk \
|
||||
libgd3 \
|
||||
&& \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN rm -rf /usr/local/tomcat/webapps/ROOT
|
||||
COPY --from=builder /app/target/plantuml.war /usr/local/tomcat/webapps/ROOT.war
|
||||
# Build Graphviz from source because there are no binary distributions for recent versions
|
||||
ARG GRAPHVIZ_VERSION
|
||||
ARG GRAPHVIZ_BUILD_DIR=/tmp/graphiz-build
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
build-essential \
|
||||
jq \
|
||||
libexpat1-dev \
|
||||
libgd-dev \
|
||||
zlib1g-dev \
|
||||
&& \
|
||||
mkdir -p $GRAPHVIZ_BUILD_DIR && \
|
||||
cd $GRAPHVIZ_BUILD_DIR && \
|
||||
GRAPHVIZ_VERSION=${GRAPHVIZ_VERSION:-$(curl -s https://gitlab.com/api/v4/projects/4207231/releases/ | jq -r '.[] | .name' | sort -V -r | head -1)} && \
|
||||
curl -o graphviz.tar.gz https://gitlab.com/api/v4/projects/4207231/packages/generic/graphviz-releases/${GRAPHVIZ_VERSION}/graphviz-${GRAPHVIZ_VERSION}.tar.gz && \
|
||||
tar -xzf graphviz.tar.gz && \
|
||||
cd graphviz-$GRAPHVIZ_VERSION && \
|
||||
./configure && \
|
||||
make && \
|
||||
make install && \
|
||||
apt-get remove -y \
|
||||
build-essential \
|
||||
jq \
|
||||
libexpat1-dev \
|
||||
libgd-dev \
|
||||
zlib1g-dev \
|
||||
&& \
|
||||
apt-get autoremove -y && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/* && \
|
||||
rm -rf $GRAPHVIZ_BUILD_DIR
|
||||
|
||||
COPY docker-entrypoint.tomcat.sh /entrypoint.sh
|
||||
RUN chmod +x /entrypoint.sh
|
||||
|
||||
ENV WEBAPP_PATH=$CATALINA_HOME/webapps
|
||||
RUN rm -rf $WEBAPP_PATH && \
|
||||
mkdir -p $WEBAPP_PATH
|
||||
COPY --from=builder /app/target/plantuml.war /plantuml.war
|
||||
|
||||
# Openshift https://docs.openshift.com/container-platform/4.9/openshift_images/create-images.html#images-create-guide-openshift_create-images
|
||||
RUN chgrp -R 0 $CATALINA_HOME && chmod -R g=u $CATALINA_HOME
|
||||
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
CMD ["catalina.sh", "run"]
|
||||
|
|
204
README.md
|
@ -1,106 +1,196 @@
|
|||
PlantUML Server
|
||||
===============
|
||||
[![Build Status](https://travis-ci.org/plantuml/plantuml-server.png?branch=master)](https://travis-ci.org/plantuml/plantuml-server)
|
||||
[![](https://images.microbadger.com/badges/image/plantuml/plantuml-server.svg)](https://microbadger.com/images/plantuml/plantuml-server "Get your own image badge on microbadger.com")
|
||||
[![Docker Pull](https://img.shields.io/docker/pulls/plantuml/plantuml-server.svg)](https://hub.docker.com/r/plantuml/plantuml-server/)
|
||||
# PlantUML Server
|
||||
|
||||
[![GNU GENERAL PUBLIC LICENSE, Version 3, 29 June 2007](https://img.shields.io/github/license/plantuml/plantuml-server.svg?color=blue)](https://www.gnu.org/licenses/gpl-3.0)
|
||||
[![latest tag](https://img.shields.io/github/v/tag/plantuml/plantuml-server)](https://github.com/plantuml/plantuml-server/tags)
|
||||
![workflow status (Main)](https://github.com/plantuml/plantuml-server/actions/workflows/main.yml/badge.svg)
|
||||
![workflow status (Tests)](https://github.com/plantuml/plantuml-server/actions/workflows/tests.yml/badge.svg)
|
||||
|
||||
[![online](https://img.shields.io/endpoint?url=https://www.plantuml.com/plantuml/badge)](https://www.plantuml.com/plantuml)
|
||||
[![rate](https://img.shields.io/endpoint?url=https://www.plantuml.com/plantuml/rate)](https://www.plantuml.com/plantuml)
|
||||
[![peak](https://img.shields.io/endpoint?url=https://www.plantuml.com/plantuml/rate?peak)](https://www.plantuml.com/plantuml)
|
||||
|
||||
[![GitHub Sponsors](https://img.shields.io/github/sponsors/plantuml?logo=github)](https://github.com/sponsors/plantuml/)
|
||||
[![docker pulls](https://img.shields.io/docker/pulls/plantuml/plantuml-server.svg?color=blue)](https://hub.docker.com/r/plantuml/plantuml-server)
|
||||
![Docker Image Size (Jetty)](https://img.shields.io/docker/image-size/plantuml/plantuml-server/jetty?label=jetty%20image%20size)
|
||||
![Docker Image Size (Tomcat)](https://img.shields.io/docker/image-size/plantuml/plantuml-server/tomcat?label=tomcat%20image%20size)
|
||||
|
||||
PlantUML Server is a web application to generate UML diagrams on-the-fly.
|
||||
|
||||
![](https://raw.githubusercontent.com/ftomassetti/plantuml-server/readme/screenshots/screenshot.png)
|
||||
|
||||
To know more about PlantUML, please visit http://plantuml.com/.
|
||||
> [PlantUML is **not** affected by the log4j vulnerability.](https://github.com/plantuml/plantuml/issues/826)
|
||||
|
||||
Requirements
|
||||
============
|
||||
> **Breaking changes**:
|
||||
> The PlantUML core removed the deprecated `ALLOW_PLANTUML_INCLUDE` environment property feature and switch to the
|
||||
> `PLANTUML_SECURITY_PROFILE` concept with version `v1.2023.9`.
|
||||
> All details about PlantUML's security can be found on <https://plantuml.com/security>.
|
||||
>
|
||||
> By default PlantUML server sets the `PLANTUML_SECURITY_PROFILE` to `INTERNET`.
|
||||
> If you need more access to e.g. other ports than 80 (http) and 443 (https) or even access to local files, please
|
||||
> consider using one of the allowlist features.
|
||||
> It is strongly advised **not** to set the `PLANTUML_SECURITY_PROFILE` below `INTERNET`!
|
||||
|
||||
* jre/jdk 1.6.0 or above
|
||||
* apache maven 3.0.2 or above
|
||||
![PlantUML Server](https://raw.githubusercontent.com/plantuml/plantuml-server/master/docs/screenshot.png)
|
||||
|
||||
How to run the server
|
||||
=====================
|
||||
More examples and features about the Web UI can be found in [docs/WebUI](https://github.com/plantuml/plantuml-server/tree/master/docs/WebUI).
|
||||
|
||||
To know more about PlantUML, please visit https://plantuml.com.
|
||||
|
||||
|
||||
## Requirements
|
||||
|
||||
- jre/jdk 11 or above
|
||||
- apache maven 3.0.2 or above
|
||||
|
||||
## Recommendations
|
||||
|
||||
- Jetty 11 or above
|
||||
- Tomcat 10 or above
|
||||
|
||||
|
||||
## How to run the server
|
||||
|
||||
Just run:
|
||||
|
||||
```
|
||||
```sh
|
||||
mvn jetty:run
|
||||
```
|
||||
|
||||
The server is now listing to [http://localhost:8080/plantuml](http://localhost:8080/plantuml).
|
||||
In this way the server is run on an embedded jetty server.
|
||||
The server is now listening to [http://localhost:8080/plantuml](http://localhost:8080/plantuml).
|
||||
In this way the server is run on an embedded jetty server.
|
||||
|
||||
You can specify the port at which it runs:
|
||||
|
||||
```
|
||||
mvn jetty:run -Djetty.port=9999
|
||||
```sh
|
||||
mvn jetty:run -Djetty.http.port=9999
|
||||
```
|
||||
|
||||
How to run the server with Docker
|
||||
=================================
|
||||
|
||||
## How to run the server with Docker
|
||||
|
||||
You can run Plantuml with jetty or tomcat container
|
||||
```
|
||||
```sh
|
||||
docker run -d -p 8080:8080 plantuml/plantuml-server:jetty
|
||||
docker run -d -p 8080:8080 plantuml/plantuml-server:tomcat
|
||||
```
|
||||
|
||||
The server is now listing to [http://localhost:8080](http://localhost:8080).
|
||||
The server is now listening to [http://localhost:8080](http://localhost:8080).
|
||||
|
||||
How to set PlantUML options
|
||||
=================================
|
||||
### Read-only container
|
||||
|
||||
You can apply some option to your PlantUML server with environement variable.
|
||||
The jetty container supports read-only files system, you can run the read-only mode with:
|
||||
```sh
|
||||
docker run -d -p 8080:8080 --read-only -v /tmp/jetty plantuml/plantuml-server:jetty
|
||||
```
|
||||
|
||||
If you run the directly the jar, you can pass the option with `-D` flag
|
||||
This makes the container compatible with more restricted environment such as OpenShift, just make sure you mount a volume (can be ephemeral) on `/tmp/jetty`.
|
||||
|
||||
### Change base URL
|
||||
|
||||
To run plantuml using different base url, change the `docker-compose.yml` file:
|
||||
```yaml
|
||||
environment:
|
||||
- BASE_URL=plantuml
|
||||
```
|
||||
java -D THE_ENV_VARIABLE=THE_ENV_VALUE -Djetty.contextpath=/ -jar target/dependency/jetty-runner.jar target/plantuml.war
|
||||
|
||||
And run `docker-compose up`. This will start a modified version of the image using the base url `/plantuml`, e.g. http://localhost:8080/plantuml
|
||||
|
||||
|
||||
## How to set PlantUML options
|
||||
|
||||
You can apply some option to your PlantUML server with environment variable.
|
||||
|
||||
If you run the directly the jar:
|
||||
```sh
|
||||
# NOTE: jetty-runner is deprecated.
|
||||
# build war file and jetty-runner
|
||||
mvn package
|
||||
# start directly
|
||||
# java $JVM_ARGS -jar jetty-runner.jar $JETTY_ARGS
|
||||
java -jar target/dependency/jetty-runner.jar --config src/main/config/jetty.xml --port 9999 --path /plantuml target/plantuml.war
|
||||
# see help for more possible options
|
||||
java -jar target/dependency/jetty-runner.jar --help
|
||||
```
|
||||
or
|
||||
```
|
||||
mvn jetty:run -D THE_ENV_VARIABLE=THE_ENV_VALUE -Djetty.port=9999
|
||||
Note: `--config src/main/config/jetty.xml` is only necessary if you need support for empty path segments in URLs (e.g. for the old proxy)
|
||||
|
||||
Alternatively, start over maven and pass the option with `-D` flag
|
||||
```sh
|
||||
mvn jetty:run -D THE_ENV_VARIABLE=THE_ENV_VALUE -Djetty.http.port=9999
|
||||
```
|
||||
|
||||
If you use docker, you can use the `-e` flag:
|
||||
```
|
||||
docker run -d -p 8080:8080 -e THE_ENV_VARIABLE=THE_ENV_VALUE plantuml/plantuml-server:jetty
|
||||
```sh
|
||||
docker run -d -p 9999:8080 -e THE_ENV_VARIABLE=THE_ENV_VALUE plantuml/plantuml-server:jetty
|
||||
```
|
||||
|
||||
You can set all the following variables:
|
||||
|
||||
* `BASE_URL`
|
||||
* PlantUML Base URL path
|
||||
* Default value: `ROOT`
|
||||
* `PLANTUML_SECURITY_PROFILE`
|
||||
* Set PlantUML security profile. See [PlantUML security](https://plantuml.com/security).
|
||||
* If you need more access to e.g. other ports than 80 (http) and 443 (https) or even access to local files, please consider using one of the allowlist features:
|
||||
* `plantuml.allowlist.path`
|
||||
* `plantuml.include.path`
|
||||
* `plantuml.allowlist.url`
|
||||
* It is strongly advised **not** to set the `PLANTUML_SECURITY_PROFILE` below `INTERNET`!
|
||||
* Default value: `INTERNET`
|
||||
* `PLANTUML_PROPERTY_FILE`
|
||||
* Set PlantUML system properties (like over the Java command line using the `-Dpropertyname=value` syntax).
|
||||
* To see what kind of file content is supported, see the documentation of [`java.util.Properties.load`](https://docs.oracle.com/javase/8/docs/api/java/util/Properties.html#load-java.io.Reader-).
|
||||
* Default value: `null`
|
||||
* `PLANTUML_CONFIG_FILE`
|
||||
* Local path to a PlantUML configuration file (identical to the `-config` flag on the CLI)
|
||||
* File content will be added before each PlantUML diagram code.
|
||||
* Default value: `null`
|
||||
* `PLANTUML_LIMIT_SIZE`
|
||||
* Limits image width and height
|
||||
* Default value `4096`
|
||||
* `GRAPHVIZ_DOT`
|
||||
* Link to 'dot' executable
|
||||
* Default value `/usr/local/bin/dot` or `/usr/bin/dot`
|
||||
* Limits image width and height
|
||||
* Default value: `4096`
|
||||
* `PLANTUML_STATS`
|
||||
* Set it to `on` to enable [statistics report](http://plantuml.com/statistics-report)
|
||||
* Default value `off`
|
||||
* Set it to `on` to enable [statistics report](https://plantuml.com/statistics-report)
|
||||
* Default value: `off`
|
||||
* `HTTP_AUTHORIZATION`
|
||||
* when calling the `proxy` endpoint, the value of `HTTP_AUTHORIZATION` will be used to set the HTTP Authorization header
|
||||
* Default value: `null`
|
||||
* `HTTP_PROXY_READ_TIMEOUT`
|
||||
* when calling the `proxy` endpoint, the value of `HTTP_PROXY_READ_TIMEOUT` will be the connection read timeout in milliseconds
|
||||
* Default value: `10000` (10 seconds)
|
||||
|
||||
|
||||
## Alternate: How to build your docker image
|
||||
|
||||
Alternate: How to build your docker image
|
||||
======================================================
|
||||
|
||||
This method uses maven to run the application. That requires internet connectivity.
|
||||
So, you can use following command to create a self-contained docker image that will "just-work".
|
||||
|
||||
*Note: Generate the WAR (instructions further below) prior to running "docker build"*
|
||||
This method uses maven to run the application. That requires internet connectivity.
|
||||
So, you can use following command to create a self-contained docker image that will "just work".
|
||||
|
||||
```sh
|
||||
docker image build -f Dockerfile.jetty -t plantuml-server:local .
|
||||
docker run -d -p 8080:8080 plantuml-server:local
|
||||
```
|
||||
docker image build -t plantuml-server .
|
||||
docker run -d -p 8080:8080 plantuml-server
|
||||
```
|
||||
The server is now listing to [http://localhost:8080/plantuml](http://localhost:8080/plantuml).
|
||||
The server is now listening to [http://localhost:8080](http://localhost:8080).
|
||||
|
||||
You may specify the port in `-p` Docker command line argument.
|
||||
|
||||
|
||||
How to generate the war
|
||||
=======================
|
||||
|
||||
## How to generate the war
|
||||
|
||||
To build the war, just run:
|
||||
|
||||
```
|
||||
```sh
|
||||
mvn package
|
||||
```
|
||||
|
||||
at the root directory of the project to produce plantuml.war in the target/ directory.
|
||||
|
||||
NOTE: If you want that the generated war includes the `apache-jsp` artifact run:
|
||||
```sh
|
||||
mvn package -Dapache-jsp.scope=compile
|
||||
```
|
||||
|
||||
If you want to generate the war with java 8 as target just remove the src/test directory and use `pom.jdk8.xml`.
|
||||
```sh
|
||||
rm -rf src/test
|
||||
mvn package -f pom.jdk8.xml [-Dapache-jsp.scope=compile]
|
||||
```
|
||||
|
||||
## Use with reverse-proxy
|
||||
|
||||
It is possible to use PlantUML with a reverse proxy.
|
||||
|
||||
You can find this and other examples [here](https://github.com/plantuml/plantuml-server/tree/master/examples).
|
||||
|
|
9
ROOT.jetty.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd">
|
||||
|
||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
<Set name="contextPath">
|
||||
<Env name="CONTEXT_PATH" />
|
||||
</Set>
|
||||
<Set name="war">/plantuml.war</Set>
|
||||
</Configure>
|
12
SECURITY.md
Normal file
|
@ -0,0 +1,12 @@
|
|||
# Security Policy
|
||||
|
||||
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
If you find any security concern, please send a mail to plantuml@gmail.com
|
||||
with title **Security concern**.
|
||||
|
||||
We will then study the concern and will answer back by email.
|
||||
|
||||
Thanks!
|
13
docker-compose.yml
Normal file
|
@ -0,0 +1,13 @@
|
|||
version: '3.3'
|
||||
|
||||
services:
|
||||
plantuml-server:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.jetty
|
||||
image: plantuml/plantuml-server:jetty
|
||||
container_name: plantuml-server
|
||||
ports:
|
||||
- 8080:8080
|
||||
environment:
|
||||
- BASE_URL=plantuml
|
14
docker-entrypoint.jetty.sh
Executable file
|
@ -0,0 +1,14 @@
|
|||
#!/bin/sh
|
||||
# cspell:words mkdir
|
||||
# cspell:enableCompoundWords
|
||||
###########################################################
|
||||
|
||||
# ensure context path starts with a slash
|
||||
export CONTEXT_PATH="/${BASE_URL#'/'}"
|
||||
|
||||
# base image entrypoint
|
||||
if [ -x /docker-entrypoint.sh ]; then
|
||||
/docker-entrypoint.sh "$@"
|
||||
else
|
||||
exec "$@"
|
||||
fi
|
18
docker-entrypoint.tomcat.sh
Executable file
|
@ -0,0 +1,18 @@
|
|||
#!/bin/sh
|
||||
# cspell:words mkdir
|
||||
# cspell:enableCompoundWords
|
||||
###########################################################
|
||||
|
||||
# choose war file name so that context path is correctly set based on BASE_URL,
|
||||
# following the rules from https://tomcat.apache.org/tomcat-9.0-doc/config/context.html#Naming,
|
||||
# specifically remove leading and trailing slashes and replace the remaining ones by hashes.
|
||||
export FILE_NAME="$(echo "$BASE_URL" | sed -e 's:^/::' -e 's:/$::' -e 's:/:#:g')"
|
||||
export FILE_PATH="$WEBAPP_PATH/$FILE_NAME.war"
|
||||
mv /plantuml.war "$FILE_PATH"
|
||||
|
||||
# base image entrypoint
|
||||
if [ -x /docker-entrypoint.sh ]; then
|
||||
/docker-entrypoint.sh "$@"
|
||||
else
|
||||
exec "$@"
|
||||
fi
|
25
docs/WebUI/README.md
Normal file
|
@ -0,0 +1,25 @@
|
|||
# PlantUML Server Web UI
|
||||
|
||||
## First example: "Alice and Bob"
|
||||
|
||||
![alice-bob](https://raw.githubusercontent.com/plantuml/plantuml-server/master/docs/WebUI/gifs/alice-bob.gif)
|
||||
|
||||
## Multipaging
|
||||
|
||||
Just see what you want.
|
||||
And if its the second diagram page, so be it.
|
||||
|
||||
![multipaging](https://raw.githubusercontent.com/plantuml/plantuml-server/master/docs/WebUI/gifs/multipaging.gif)
|
||||
|
||||
## Split Screen
|
||||
|
||||
You have multiple monitors? You want to share your Window but only show the diagram and not the code? Than do it!
|
||||
|
||||
![multipaging](https://raw.githubusercontent.com/plantuml/plantuml-server/master/docs/WebUI/gifs/split-screen.gif)
|
||||
|
||||
## More
|
||||
|
||||
- [Settings](https://github.com/plantuml/plantuml-server/blob/master/docs/WebUI/settings.md)
|
||||
- [PlantUML Language Features](https://github.com/plantuml/plantuml-server/blob/master/docs/WebUI/language-features.md)
|
||||
- [Import/Export](https://github.com/plantuml/plantuml-server/blob/master/docs/WebUI/import-export.md)
|
||||
- [Mobile Version](https://github.com/plantuml/plantuml-server/blob/master/docs/WebUI/mobile.md)
|
BIN
docs/WebUI/gifs/alice-bob.gif
Normal file
After Width: | Height: | Size: 83 KiB |
BIN
docs/WebUI/gifs/auto-completion-emojis.gif
Normal file
After Width: | Height: | Size: 142 KiB |
BIN
docs/WebUI/gifs/auto-completion-icons.gif
Normal file
After Width: | Height: | Size: 116 KiB |
BIN
docs/WebUI/gifs/auto-completion-themes+icons.gif
Normal file
After Width: | Height: | Size: 272 KiB |
BIN
docs/WebUI/gifs/auto-completion-themes.gif
Normal file
After Width: | Height: | Size: 129 KiB |
BIN
docs/WebUI/gifs/diagram-export.gif
Normal file
After Width: | Height: | Size: 296 KiB |
BIN
docs/WebUI/gifs/diagram-import.gif
Normal file
After Width: | Height: | Size: 1.5 MiB |
BIN
docs/WebUI/gifs/mobile-alice-bob.gif
Normal file
After Width: | Height: | Size: 110 KiB |
BIN
docs/WebUI/gifs/mobile-settings.gif
Normal file
After Width: | Height: | Size: 253 KiB |
BIN
docs/WebUI/gifs/multipaging.gif
Normal file
After Width: | Height: | Size: 259 KiB |
BIN
docs/WebUI/gifs/settings-rendering-type.gif
Normal file
After Width: | Height: | Size: 575 KiB |
BIN
docs/WebUI/gifs/settings-theme.gif
Normal file
After Width: | Height: | Size: 460 KiB |
BIN
docs/WebUI/gifs/split-screen.gif
Normal file
After Width: | Height: | Size: 211 KiB |
BIN
docs/WebUI/gifs/validation-start-end.gif
Normal file
After Width: | Height: | Size: 255 KiB |
21
docs/WebUI/import-export.md
Normal file
|
@ -0,0 +1,21 @@
|
|||
# Import and Export editable PlantUML Diagrams
|
||||
|
||||
Similar to [draw.io](https://app.diagrams.net) it is possible to load and continue editing PlantUML diagram images.
|
||||
|
||||
|
||||
## Export a diagram
|
||||
|
||||
Via the editor menu or <kbd>Ctrl</kbd> + <kbd>S</kbd> (or <kbd>Meta</kbd> + <kbd>S</kbd> in the case of a Mac) you can open the file save dialog.
|
||||
Here you can edit the file name, choose a file/diagram type and download the diagram.
|
||||
The default is to download the PlantUML code.
|
||||
|
||||
![export](https://raw.githubusercontent.com/plantuml/plantuml-server/master/docs/WebUI/gifs/diagram-export.gif)
|
||||
|
||||
|
||||
## Import a diagram
|
||||
|
||||
This feature is based on the PlantUML meta data which currently **support only PNG and SVG** diagrams.
|
||||
Besides a diagram image, you can of course also load a diagram code file.
|
||||
Moreover, because it is so nice and convenient, we also added a drag-and-drop feature.
|
||||
|
||||
![import](https://raw.githubusercontent.com/plantuml/plantuml-server/master/docs/WebUI/gifs/diagram-import.gif)
|
41
docs/WebUI/language-features.md
Normal file
|
@ -0,0 +1,41 @@
|
|||
# PlantUML Language Features
|
||||
|
||||
## Auto Completion
|
||||
|
||||
### Icons
|
||||
|
||||
- type `<&` to get a list of PlantUML available icons
|
||||
- see a preview of the suggested icon in its description
|
||||
- [PlantUML documentation](https://plantuml.com/openiconic)
|
||||
|
||||
![icons](https://raw.githubusercontent.com/plantuml/plantuml-server/master/docs/WebUI/gifs/auto-completion-icons.gif)
|
||||
|
||||
### Emojis
|
||||
|
||||
- type `<:` to get a list of PlantUML available icons
|
||||
- see a preview of the suggested icon in its description
|
||||
- [PlantUML documentation](https://plantuml.com/creole#68305e25f5788db0)
|
||||
|
||||
![emojis](https://raw.githubusercontent.com/plantuml/plantuml-server/master/docs/WebUI/gifs/auto-completion-emojis.gif)
|
||||
|
||||
### Themes
|
||||
|
||||
- type `!t` to get the suggestion `theme`
|
||||
- type `!theme ` to get a list of (local) available PlantUML themes.
|
||||
- [PlantUML documentation](https://plantuml.com/theme)
|
||||
|
||||
![themes](https://raw.githubusercontent.com/plantuml/plantuml-server/master/docs/WebUI/gifs/auto-completion-themes.gif)
|
||||
|
||||
|
||||
## Validation
|
||||
|
||||
### `@start...` and `@end...`
|
||||
|
||||
- `@start...` should always be the first command
|
||||
- `@end...` should alway be the last command
|
||||
- `@start...` should only exists once
|
||||
- `@end...` should only exists once
|
||||
- `@end...` should have the same type as `@start...`
|
||||
e.g.: `@startjson ... @endjson`
|
||||
|
||||
![start-end](https://raw.githubusercontent.com/plantuml/plantuml-server/master/docs/WebUI/gifs/validation-start-end.gif)
|
12
docs/WebUI/mobile.md
Normal file
|
@ -0,0 +1,12 @@
|
|||
# Mobile Version
|
||||
|
||||
PlantUML Server is mobile ready.
|
||||
|
||||
## First example: "Alice and Bob"
|
||||
|
||||
![alice-bob](https://raw.githubusercontent.com/plantuml/plantuml-server/master/docs/WebUI/gifs/mobile-alice-bob.gif)
|
||||
|
||||
|
||||
## Settings
|
||||
|
||||
![settings](https://raw.githubusercontent.com/plantuml/plantuml-server/master/docs/WebUI/gifs/mobile-settings.gif)
|
38
docs/WebUI/settings.md
Normal file
|
@ -0,0 +1,38 @@
|
|||
# Settings
|
||||
|
||||
Via the menu or <kbd>Ctrl</kbd> + <kbd>,</kbd> (or <kbd>Meta</kbd> + <kbd>,</kbd> in the case of a Mac) you can open the Setting dialog.
|
||||
|
||||
## Theme
|
||||
|
||||
_The sun is too bright? You live on the dark side or only in the basement?_
|
||||
Choose between the `dark` and `light` theme.
|
||||
|
||||
![theme](https://raw.githubusercontent.com/plantuml/plantuml-server/master/docs/WebUI/gifs/settings-theme.gif)
|
||||
|
||||
## Rendering Type
|
||||
|
||||
You want always to work and see only the SVG version? Not Problem.
|
||||
Choose the rendering type you want to see.
|
||||
|
||||
![rendering-type](https://raw.githubusercontent.com/plantuml/plantuml-server/master/docs/WebUI/gifs/settings-rendering-type.gif)
|
||||
|
||||
## Editor Watcher Timeout
|
||||
|
||||
You can change the Editor Watcher Timeout, by default it is `500 ms`.
|
||||
|
||||
|
||||
## Editor Options
|
||||
|
||||
You can change the options of the editor:
|
||||
|
||||
```yaml
|
||||
{
|
||||
automaticLayout: true,
|
||||
fixedOverflowWidgets: true,
|
||||
minimap: { enabled: false },
|
||||
scrollbar: { alwaysConsumeMouseWheel: false },
|
||||
scrollBeyondLastLine: false,
|
||||
tabSize: 2,
|
||||
theme: "vs", // "vs-dark"
|
||||
}
|
||||
```
|
83
docs/contribution/front-end.md
Normal file
|
@ -0,0 +1,83 @@
|
|||
# Front-end Contribution
|
||||
|
||||
## Web UI
|
||||
|
||||
The Web UI uses vanilla javascript.
|
||||
|
||||
As online editor Microsoft's [Monaco Editor](https://github.com/microsoft/monaco-editor).
|
||||
The documentation can be found [here](https://microsoft.github.io/monaco-editor/docs.html).
|
||||
You may recognize the editor since it's the code editor from [VS Code](https://github.com/microsoft/vscode).
|
||||
|
||||
The main entry file are `index.jsp`, `previewer.jsp` and `error.jsp`.
|
||||
|
||||
The code structure is mainly divided into `components` and `js`:
|
||||
- `components` are for example a modal or dialog.
|
||||
Anything that include things directly seen and rendered on the page.
|
||||
- `js` contains more the things that do not have a direct influence on the UI. For example the PlantUML language features or the methods for cross-browser/cross-tab communication.
|
||||
|
||||
|
||||
## PlantUML Language Features
|
||||
|
||||
At the moment there is no defined PlantUML language.
|
||||
Feel free to create one!
|
||||
But until then the syntax highlighting form `apex` is used.
|
||||
IMHO it works quite well.
|
||||
|
||||
All PlantUML language features are bundled into a seperate file `plantuml-language.min.js`.
|
||||
Therefore anything under `js/language` should be independent!
|
||||
|
||||
### Code Completion
|
||||
What do you need to do to create a new code completion feature:
|
||||
1. create a new JS file under `js/language/completion` - let's say `xxx.js`
|
||||
2. create a new `registerXxxCompletion` method
|
||||
_It may help you if you look into the [documentation](https://microsoft.github.io/monaco-editor/docs.html#functions/languages.registerCompletionItemProvider.html) or at the provided [sample code](https://microsoft.github.io/monaco-editor/playground.html?source=v0.38.0#example-extending-language-services-completion-provider-example) to understand more about `monaco.languages.registerCompletionItemProvider`._
|
||||
```js
|
||||
PlantUmlLanguageFeatures.prototype.registerEmojiCompletion = function() {
|
||||
monaco.languages.registerCompletionItemProvider(PlantUmlLanguageFeatures.languageSelector, {
|
||||
provideCompletionItems: async (model, position) => {
|
||||
// ...
|
||||
return { suggestions };
|
||||
}
|
||||
});
|
||||
};
|
||||
```
|
||||
4. add your new method inside the language initialization inside `js/language/language.js`
|
||||
```diff
|
||||
const PlantUmlLanguageFeatures = function(initialize = true) {
|
||||
if (initialize) {
|
||||
// initialize all validation and code completion methods
|
||||
this.addStartEndValidationListeners();
|
||||
this.registerThemeCompletion();
|
||||
this.registerIconCompletion();
|
||||
this.registerEmojiCompletion();
|
||||
+ this.registerXxxCompletion();
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### Code Validation
|
||||
What do you need to do to create a new code validation feature:
|
||||
1. create a new JS file under `js/language/validation/listeners` - let's say `zzz-validation.js`
|
||||
2. register your validation methods to the designated event listener
|
||||
The validation event order is: `before` → `code` → `line` → `after`
|
||||
You may look at `js/language/validation/listeners/start-end-validation.js` to get an idea how to register a new listener.
|
||||
3. add your new method inside the language initialization inside `js/language/language.js`
|
||||
```diff
|
||||
const PlantUmlLanguageFeatures = function(initialize = true) {
|
||||
if (initialize) {
|
||||
// initialize all validation and code completion methods
|
||||
this.addStartEndValidationListeners();
|
||||
+ this.addZzzValidationListeners();
|
||||
this.registerThemeCompletion();
|
||||
this.registerIconCompletion();
|
||||
this.registerEmojiCompletion();
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
### Tipps
|
||||
|
||||
- `pom.xml`: set `withoutCSSJSCompress` to `true` to deactivate the minification
|
||||
- use `mvn fizzed-watcher:run` to watch changes and automatically update the bundled `plantuml.min.{css,js}` and `plantuml-language.min.js` files
|
||||
- if the browser get the error `ReferenceError: require is not defined` or something similar related to the webjars, try `mvn clean install` to get things straight
|
BIN
docs/screenshot.png
Normal file
After Width: | Height: | Size: 48 KiB |
6
examples/README.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
# Examples
|
||||
|
||||
- [Additional fonts inside the PlantUML docker container](./additional-fonts)
|
||||
- [Nginx simple reverse proxy example](./nginx-simple)
|
||||
- [Nginx reverse proxy example with defined location directive (different context path)](./nginx-contextpath)
|
||||
- [Kubernetes simple deployment](./kubernetes-simple)
|
73
examples/additional-fonts/README.md
Normal file
|
@ -0,0 +1,73 @@
|
|||
# Additional fonts inside the PlantUML docker container
|
||||
|
||||
It is possible to make additional fonts available to PlantUML by mapping them via a volume within the docker container.
|
||||
|
||||
Since the base image from the docker container is using Ubuntu, fonts can easily be provided by just adding them somewhere inside the `~/.local/share/fonts` directory.
|
||||
|
||||
**Tipp**: to not overwrite the container fonts add the additional files inside an own sub-folder, e.g., `custom` or `host`.
|
||||
|
||||
In the following you can find an example how to provide all fonts of your host machine in the PlantUML docker container for Jetty and Tomcat.
|
||||
|
||||
|
||||
## Jetty
|
||||
|
||||
In the case of the Jetty docker container the home directory is `/var/lib/jetty`.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
plantuml-server:
|
||||
image: plantuml/plantuml-server:jetty
|
||||
container_name: plantuml-server
|
||||
ports:
|
||||
- "80:8080"
|
||||
environment:
|
||||
- TZ=Europe/Berlin
|
||||
- BASE_URL=plantuml
|
||||
volumes:
|
||||
- /usr/share/fonts:/var/lib/jetty/.local/share/fonts/host:ro
|
||||
```
|
||||
|
||||
|
||||
## Tomcat
|
||||
|
||||
In the case of the Tomcat docker container the home directory is `/root`.
|
||||
_Yes, the tomcat container is running as `root` which is basically a really bad idea w.r.t. security. Create a pull request and maintain it if you want to change that._
|
||||
|
||||
```yaml
|
||||
services:
|
||||
plantuml-server:
|
||||
image: plantuml/plantuml-server:tomcat
|
||||
container_name: plantuml-server
|
||||
ports:
|
||||
- "80:8080"
|
||||
environment:
|
||||
- TZ=Europe/Berlin
|
||||
- BASE_URL=plantuml
|
||||
volumes:
|
||||
- /usr/share/fonts:/root/.local/share/fonts/host:ro
|
||||
```
|
||||
|
||||
|
||||
## Verification
|
||||
|
||||
The following command will print a list of all available fonts inside the docker container:
|
||||
|
||||
```bash
|
||||
docker exec -it plantuml-server fc-list
|
||||
```
|
||||
|
||||
To find a special font add a grep filter to the command:
|
||||
|
||||
```bash
|
||||
docker exec -it plantuml-server fc-list | grep "<name-of-font>"
|
||||
```
|
||||
|
||||
Naturally, it is also possible to check this via PlantUML itself by rendering the following diagram:
|
||||
|
||||
```plantuml
|
||||
@startuml
|
||||
listfonts
|
||||
@enduml
|
||||
```
|
||||
|
||||
**Note**: If you have added a lot of fonts: (a) this diagram may take a few seconds to generate, and (b) eventually the PNG image may be clipped. To avoid the latter, render the diagram as an SVG image.
|
13
examples/additional-fonts/docker-compose.yml
Normal file
|
@ -0,0 +1,13 @@
|
|||
version: "3"
|
||||
|
||||
services:
|
||||
plantuml-server:
|
||||
image: plantuml/plantuml-server:jetty
|
||||
container_name: plantuml-server
|
||||
ports:
|
||||
- "80:8080"
|
||||
environment:
|
||||
- TZ=Europe/Berlin
|
||||
- BASE_URL=plantuml
|
||||
volumes:
|
||||
- /usr/share/fonts:/var/lib/jetty/.local/share/fonts/host:ro
|
51
examples/kubernetes-simple/README.md
Normal file
|
@ -0,0 +1,51 @@
|
|||
# PlantUML Kubernetes Deployment
|
||||
|
||||
In this example, PlantUML is deployed on an Kubernetes cluster using a `Deployment`, a `Service` and an `Ingress`.
|
||||
|
||||
## Quick start
|
||||
|
||||
Install:
|
||||
|
||||
```bash
|
||||
# Hint: Adjust the Ingress host to your URL
|
||||
|
||||
kubectl create ns plantuml
|
||||
kubectl -n plantuml apply -f deployment.yaml
|
||||
```
|
||||
|
||||
Uninstall:
|
||||
|
||||
```bash
|
||||
kubectl -n plantuml delete -f deployment.yaml
|
||||
kubectl delete ns plantuml
|
||||
```
|
||||
|
||||
## TLS configuration
|
||||
|
||||
Create a TLS `Secret` and extend the `Ingress` spec with a TLS configuration:
|
||||
|
||||
```bash
|
||||
[...]
|
||||
tls:
|
||||
- hosts:
|
||||
- plantuml-example.localhost
|
||||
secretName: plantuml-tls
|
||||
```
|
||||
|
||||
Since the `Ingress Controller` terminates the TLS and routes `http` to the application, we might need to tell the application explicitly that it got a forwarded request.
|
||||
|
||||
This configuration changes depending on the `Ingress Controller`. Here an nginx example:
|
||||
|
||||
```
|
||||
annotations:
|
||||
kubernetes.io/ingress.class: nginx
|
||||
nginx.ingress.kubernetes.io/configuration-snippet: |
|
||||
more_set_headers "X-Forwarded-Proto: https";
|
||||
```
|
||||
|
||||
## Useful commands
|
||||
|
||||
```bash
|
||||
# see whats going on inside your Deployment
|
||||
kubectl -n plantuml logs -l "app.kubernetes.io/name=plantuml"
|
||||
```
|
84
examples/kubernetes-simple/deployment.yaml
Normal file
|
@ -0,0 +1,84 @@
|
|||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: plantuml
|
||||
labels:
|
||||
app.kubernetes.io/name: plantuml
|
||||
app.kubernetes.io/instance: plantuml
|
||||
spec:
|
||||
replicas: 3 # Can be adjusted
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: plantuml
|
||||
app.kubernetes.io/instance: plantuml
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: plantuml
|
||||
app.kubernetes.io/instance: plantuml
|
||||
spec:
|
||||
containers:
|
||||
- name: plantuml
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
image: plantuml/plantuml-server:jetty-v1.2022.6
|
||||
imagePullPolicy: Always
|
||||
# env: # In case of different base URL
|
||||
# - name: BASE_URL
|
||||
# value: plantuml
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 8080
|
||||
protocol: TCP
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: http
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: http
|
||||
resources:
|
||||
limits:
|
||||
cpu: 500m
|
||||
memory: 2048Mi
|
||||
requests:
|
||||
cpu: 250m
|
||||
memory: 1024Mi
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: plantuml
|
||||
labels:
|
||||
app.kubernetes.io/name: plantuml
|
||||
app.kubernetes.io/instance: plantuml
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
app.kubernetes.io/name: plantuml
|
||||
app.kubernetes.io/instance: plantuml
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: plantuml
|
||||
labels:
|
||||
app.kubernetes.io/name: plantuml
|
||||
app.kubernetes.io/instance: plantuml
|
||||
spec:
|
||||
rules:
|
||||
- host: plantuml-example.localhost
|
||||
http:
|
||||
paths:
|
||||
- backend:
|
||||
service:
|
||||
name: plantuml
|
||||
port:
|
||||
number: 80
|
||||
path: /
|
||||
pathType: Prefix
|
119
examples/nginx-contextpath/README.md
Normal file
|
@ -0,0 +1,119 @@
|
|||
# Nginx reverse proxy example with defined location directive
|
||||
|
||||
In this example, the reverse proxy is defined only under the `/plantuml` context path.
|
||||
All other context paths (locations) are not affected and are freely available.
|
||||
This allows the server to be used for more than "just" PlantUML.
|
||||
|
||||
References:
|
||||
- [Nginx documentation](https://nginx.org/en/docs/)
|
||||
- [Nginx beginner's guide](https://nginx.org/en/docs/beginners_guide.html)
|
||||
|
||||
|
||||
## Quick start
|
||||
|
||||
Be sure to have [`docker-compose.yml`](./docker-compose.yml) and [`nginx.conf`](./nginx.conf) inside your current working directory.
|
||||
|
||||
```bash
|
||||
# start nginx and plantuml server
|
||||
docker-compose up -d
|
||||
|
||||
# stop nginx and plantuml server
|
||||
docker-compose down
|
||||
```
|
||||
|
||||
Check with `docker ps` if both container are up and running:
|
||||
|
||||
```
|
||||
$ docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
217e753a0dcf plantuml/plantuml-server:jetty "/entrypoint.sh" 4 seconds ago Up 3 seconds 8080/tcp plantuml-server
|
||||
9b1290c100f5 nginx:alpine "/docker-entrypoint.…" 4 seconds ago Up 3 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp nginx
|
||||
```
|
||||
|
||||
Open [http://localhost/plantuml](http://localhost/plantuml) inside your browser.
|
||||
YEAH! You are now using PlantUML behind a simple Nginx reverse proxy.
|
||||
|
||||
|
||||
## Nginx configuration
|
||||
|
||||
```nginx
|
||||
...
|
||||
|
||||
# PlantUML
|
||||
location /plantuml/ {
|
||||
proxy_pass http://plantuml-server:8080/plantuml/;
|
||||
}
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
- `location /plantuml/` to reverse only the context path `/plantuml`
|
||||
- `proxy_pass http://plantuml-server:8080/plantuml/` to set reverse proxy path to plantuml server.
|
||||
Use the docker container name `plantuml-server` instead of ip addresses.
|
||||
Also, use the same context path (`BASE_URL`) as PlantUML, which is configurable as an environment variable in the docker-compose file.
|
||||
|
||||
NOTE: `BASE_URL`, `location` and therefore the `proxy_pass` should have the some context path!
|
||||
If that is not possible it may be possible to solve the problem by using NGINX `sub_filter`:
|
||||
```nginx
|
||||
# PlantUML
|
||||
location /plantuml/ {
|
||||
sub_filter '<base href="/" />' '<base href="/plantuml/" />';
|
||||
sub_filter_types text/html;
|
||||
|
||||
proxy_pass http://plantuml-server:8080/;
|
||||
}
|
||||
```
|
||||
|
||||
NOTE: Since [PR#256](https://github.com/plantuml/plantuml-server/pull/256) it is possible to use deep base URLs.
|
||||
So with e.g. `BASE_URL=foo/bar` the following is possible:
|
||||
```nginx
|
||||
# PlantUML
|
||||
location /foo/bar/ {
|
||||
proxy_pass http://plantuml-server:8080/foo/bar/;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Nginx and PlantUML server
|
||||
|
||||
```yaml
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
plantuml-server:
|
||||
image: plantuml/plantuml-server:jetty
|
||||
container_name: plantuml-server
|
||||
environment:
|
||||
- TZ=Europe/Berlin
|
||||
- BASE_URL=plantuml
|
||||
|
||||
nginx:
|
||||
image: nginx:alpine
|
||||
container_name: nginx
|
||||
ports:
|
||||
- "80:80"
|
||||
environment:
|
||||
- TZ=Europe/Berlin
|
||||
volumes:
|
||||
- ./nginx.conf:/etc/nginx/nginx.conf:ro
|
||||
```
|
||||
|
||||
- Set `container_name` to use them instead of e.g. ip addresses
|
||||
- Set the environment `TZ` the ensure the same timezone.
|
||||
For example to server timezone (`cat /etc/timezone`)?
|
||||
- plantuml-server
|
||||
* plantuml-server already exposes port `8080` to it's own local network (but not outside).
|
||||
Since plantuml-server and nginx are sharing a network, nginx can reach plantuml-server without further settings.
|
||||
* Set the environment `BASE_URL` to the preferred context path
|
||||
- nginx
|
||||
* open/link port `80` to the outside
|
||||
* `./nginx.conf:/etc/nginx/nginx.conf:ro` to use your own Nginx configuration (readonly)
|
||||
|
||||
|
||||
## Useful commands
|
||||
|
||||
```bash
|
||||
# see whats going on inside your docker containers
|
||||
docker logs --tail 50 --follow --timestamps nginx
|
||||
docker logs --tail 50 --follow --timestamps plantuml-server
|
||||
```
|
19
examples/nginx-contextpath/docker-compose.yml
Normal file
|
@ -0,0 +1,19 @@
|
|||
version: "3"
|
||||
|
||||
services:
|
||||
plantuml-server:
|
||||
image: plantuml/plantuml-server:jetty
|
||||
container_name: plantuml-server
|
||||
environment:
|
||||
- TZ=Europe/Berlin
|
||||
- BASE_URL=plantuml
|
||||
|
||||
nginx:
|
||||
image: nginx:alpine
|
||||
container_name: nginx
|
||||
ports:
|
||||
- "80:80"
|
||||
environment:
|
||||
- TZ=Europe/Berlin
|
||||
volumes:
|
||||
- ./nginx.conf:/etc/nginx/nginx.conf:ro
|
44
examples/nginx-contextpath/nginx.conf
Normal file
|
@ -0,0 +1,44 @@
|
|||
user nginx;
|
||||
worker_processes auto;
|
||||
|
||||
error_log /var/log/nginx/error.log notice;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
include /etc/nginx/modules-enabled/*.conf;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
|
||||
# PlantUML
|
||||
location /plantuml/ {
|
||||
proxy_pass http://plantuml-server:8080/plantuml/;
|
||||
}
|
||||
}
|
||||
|
||||
client_max_body_size 0;
|
||||
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
access_log /var/log/nginx/access.log main;
|
||||
|
||||
sendfile on;
|
||||
#tcp_nopush on;
|
||||
|
||||
keepalive_timeout 65;
|
||||
|
||||
#gzip on;
|
||||
|
||||
include /etc/nginx/conf.d/*.conf;
|
||||
}
|
97
examples/nginx-simple/README.md
Normal file
|
@ -0,0 +1,97 @@
|
|||
# Nginx simple reverse proxy example
|
||||
|
||||
References:
|
||||
- [Nginx documentation](https://nginx.org/en/docs/)
|
||||
- [Nginx beginner's guide](https://nginx.org/en/docs/beginners_guide.html)
|
||||
|
||||
|
||||
## Quick start
|
||||
|
||||
Be sure to have [`docker-compose.yml`](./docker-compose.yml) and [`nginx.conf`](./nginx.conf) inside your current working directory.
|
||||
|
||||
```bash
|
||||
# start nginx and plantuml server
|
||||
docker-compose up -d
|
||||
|
||||
# stop nginx and plantuml server
|
||||
docker-compose down
|
||||
```
|
||||
|
||||
Check with `docker ps` if both container are up and running:
|
||||
|
||||
```
|
||||
$ docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
217e753a0dcf plantuml/plantuml-server:jetty "/entrypoint.sh" 4 seconds ago Up 3 seconds 8080/tcp plantuml-server
|
||||
9b1290c100f5 nginx:alpine "/docker-entrypoint.…" 4 seconds ago Up 3 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp nginx
|
||||
```
|
||||
|
||||
Open [http://localhost](http://localhost) inside your browser.
|
||||
YEAH! You are now using PlantUML behind a simple Nginx reverse proxy.
|
||||
|
||||
|
||||
## Nginx configuration
|
||||
|
||||
```nginx
|
||||
...
|
||||
|
||||
# PlantUML
|
||||
location / {
|
||||
proxy_set_header HOST $host;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
proxy_pass http://plantuml-server:8080/;
|
||||
}
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
- `location /` to reverse complete server
|
||||
- `proxy_set_header HOST $host` and `proxy_set_header X-Forwarded-Host $host` to replaces local plantuml server ip with FQDN
|
||||
- `proxy_set_header X-Forwarded-Proto $scheme` to use reverse proxy protocol schema instead of communication schema between reverse proxy and plantuml server
|
||||
- `proxy_pass http://plantuml-server:8080/` to set reverse proxy path to plantuml server.
|
||||
Use the docker container name `plantuml-server` instead of ip addresses.
|
||||
|
||||
|
||||
## Nginx and PlantUML server
|
||||
|
||||
```yaml
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
plantuml-server:
|
||||
image: plantuml/plantuml-server:jetty
|
||||
container_name: plantuml-server
|
||||
environment:
|
||||
- TZ=Europe/Berlin
|
||||
|
||||
nginx:
|
||||
image: nginx:alpine
|
||||
container_name: nginx
|
||||
ports:
|
||||
- "80:80"
|
||||
environment:
|
||||
- TZ=Europe/Berlin
|
||||
volumes:
|
||||
- ./nginx.conf:/etc/nginx/nginx.conf:ro
|
||||
```
|
||||
|
||||
- Set `container_name` to use them instead of e.g. ip addresses
|
||||
- Set the environment `TZ` the ensure the same timezone.
|
||||
For example to server timezone (`cat /etc/timezone`)?
|
||||
- plantuml-server
|
||||
* plantuml-server already exposes port `8080` to it's own local network (but not outside).
|
||||
Since plantuml-server and nginx are sharing a network, nginx can reach plantuml-server without further settings.
|
||||
- nginx
|
||||
* open/link port `80` to the outside
|
||||
* `./nginx.conf:/etc/nginx/nginx.conf:ro` to use your own Nginx configuration (readonly)
|
||||
|
||||
|
||||
## Useful commands
|
||||
|
||||
```bash
|
||||
# see whats going on inside your docker containers
|
||||
docker logs --tail 50 --follow --timestamps nginx
|
||||
docker logs --tail 50 --follow --timestamps plantuml-server
|
||||
```
|
18
examples/nginx-simple/docker-compose.yml
Normal file
|
@ -0,0 +1,18 @@
|
|||
version: "3"
|
||||
|
||||
services:
|
||||
plantuml-server:
|
||||
image: plantuml/plantuml-server:jetty
|
||||
container_name: plantuml-server
|
||||
environment:
|
||||
- TZ=Europe/Berlin
|
||||
|
||||
nginx:
|
||||
image: nginx:alpine
|
||||
container_name: nginx
|
||||
ports:
|
||||
- "80:80"
|
||||
environment:
|
||||
- TZ=Europe/Berlin
|
||||
volumes:
|
||||
- ./nginx.conf:/etc/nginx/nginx.conf:ro
|
48
examples/nginx-simple/nginx.conf
Normal file
|
@ -0,0 +1,48 @@
|
|||
user nginx;
|
||||
worker_processes auto;
|
||||
|
||||
error_log /var/log/nginx/error.log notice;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
include /etc/nginx/modules-enabled/*.conf;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
|
||||
# PlantUML
|
||||
location / {
|
||||
proxy_set_header HOST $host;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
proxy_pass http://plantuml-server:8080/;
|
||||
}
|
||||
}
|
||||
|
||||
client_max_body_size 0;
|
||||
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
access_log /var/log/nginx/access.log main;
|
||||
|
||||
sendfile on;
|
||||
#tcp_nopush on;
|
||||
|
||||
keepalive_timeout 65;
|
||||
|
||||
#gzip on;
|
||||
|
||||
include /etc/nginx/conf.d/*.conf;
|
||||
}
|
82
pom.jdk8.xml
Normal file
|
@ -0,0 +1,82 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||
>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.sourceforge.plantuml</groupId>
|
||||
<artifactId>plantumlservlet-parent</artifactId>
|
||||
<version>1-SNAPSHOT</version>
|
||||
<relativePath>pom.parent.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>plantumlservlet</artifactId>
|
||||
<packaging>war</packaging>
|
||||
|
||||
|
||||
<properties>
|
||||
<java.version>8</java.version>
|
||||
|
||||
<!-- build plugin management -->
|
||||
<!-- no JDK8 support starting version 10.0.0 -->
|
||||
<checkstyle.version>9.3</checkstyle.version>
|
||||
|
||||
<!-- plugins -->
|
||||
<!-- no JDK8 support starting version 2.5.0 -->
|
||||
<resources-optimizer-maven-plugin.version>2.4.4</resources-optimizer-maven-plugin.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
<artifactId>jakarta.servlet-api</artifactId>
|
||||
<version>5.0.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>apache-jsp</artifactId>
|
||||
<version>${apache-jsp.version}</version>
|
||||
<scope>${apache-jsp.scope}</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-jakarta-servlet-api</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-schemas</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-annotations</artifactId>
|
||||
<version>${jetty-annotations.version}</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-jakarta-servlet-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- Testing -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-server</artifactId>
|
||||
<version>${jetty-server.version}</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-jakarta-servlet-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
673
pom.parent.xml
Normal file
|
@ -0,0 +1,673 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||
>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.sourceforge.plantuml</groupId>
|
||||
<artifactId>plantumlservlet-parent</artifactId>
|
||||
<version>1-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>PlantUML Servlet</name>
|
||||
<url>https://plantuml.github.io/plantuml-server/index.html</url>
|
||||
|
||||
<properties>
|
||||
<!-- NOTE: property `java.version` has to be set inside the child pom. -->
|
||||
<!-- <java.version>XX</java.version> -->
|
||||
|
||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
|
||||
<!--
|
||||
Skip tests by default.
|
||||
Run tests manually:
|
||||
- mvn test -DskipTests=false
|
||||
- mvn test -DskipTests=false -DargLine="-Dsystem.test.server=http://localhost:8080/plantuml"
|
||||
-->
|
||||
<skipTests>true</skipTests>
|
||||
<!--
|
||||
JS and CSS compression / minify
|
||||
If false minify is enabled.
|
||||
Dev Tipp: set to `true` and run `mvn fizzed-watcher:run` while developing the frontend
|
||||
-->
|
||||
<withoutCSSJSCompress>false</withoutCSSJSCompress>
|
||||
|
||||
<!--
|
||||
This artifact is required for:
|
||||
1. EmbeddedJettyServer -> scope: test
|
||||
2. Tomcat docker image -> scope: compile
|
||||
BUT: Jetty docker image as well as jetty-runner will crash on runtime if
|
||||
this artifact is included because it's already provided so that the
|
||||
artifact would apear multiple times on the classpath.
|
||||
You can test it via: `mvn jetty:run [-Dapache-jsp.scope=compile]`
|
||||
Error: java.util.ServiceConfigurationError: org.apache.juli.logging.Log: org.eclipse.jetty.apache.jsp.JuliLog not a subtype
|
||||
HENCE: Default is the "test" scope and for Tomcat docker image building add:
|
||||
-Dapache-jsp.scope=compile
|
||||
-->
|
||||
<apache-jsp.scope>test</apache-jsp.scope>
|
||||
|
||||
<maven.build.timestamp.format>yyyyMMdd-HHmm</maven.build.timestamp.format>
|
||||
<timestamp>${maven.build.timestamp}</timestamp>
|
||||
|
||||
<wtp.version>1.5</wtp.version>
|
||||
<wtp.contextName>plantuml</wtp.contextName>
|
||||
|
||||
<jetty.http.port>8080</jetty.http.port>
|
||||
<jetty.contextpath>/${wtp.contextName}</jetty.contextpath>
|
||||
|
||||
<!-- main versions -->
|
||||
<plantuml.version>1.2024.5</plantuml.version>
|
||||
<!-- Please keep the jetty version identical with the docker image -->
|
||||
<jetty.version>11.0.18</jetty.version>
|
||||
<!--
|
||||
While changing the version, please update the versions in the following files as well:
|
||||
- src/main/webapp/components/app-head.jsp (script import)
|
||||
- src/main/webapp/components/editor/editor.js : loadMonacoCodeEditorAsync (require.config)
|
||||
- src/test/java/net/sourceforge/plantuml/servlet/TestDependencies.java : testMonacoEditorWebJar (JUnit Test)
|
||||
-->
|
||||
<monaco-editor.version>0.36.1</monaco-editor.version>
|
||||
|
||||
<!-- dependencies -->
|
||||
<jstl.version>1.2</jstl.version>
|
||||
<apache-jsp.version>${jetty.version}</apache-jsp.version>
|
||||
<jetty-annotations.version>${jetty.version}</jetty-annotations.version>
|
||||
<glassfish-jstl.version>${jetty.version}</glassfish-jstl.version>
|
||||
<!-- jlatexmath -->
|
||||
<jlatexmath.version>1.0.7</jlatexmath.version>
|
||||
<jlatexmath-font-greek.version>${jlatexmath.version}</jlatexmath-font-greek.version>
|
||||
<jlatexmath-font-cyrillic.version>${jlatexmath.version}</jlatexmath-font-cyrillic.version>
|
||||
<!-- PDF -->
|
||||
<batik.version>1.16</batik.version>
|
||||
<fop.version>2.8</fop.version>
|
||||
|
||||
<!-- Testing -->
|
||||
<junit.version>5.9.3</junit.version>
|
||||
<junit-suite.version>1.9.3</junit-suite.version>
|
||||
<selenium.version>4.10.0</selenium.version>
|
||||
<selenium-webdrivermanager.version>5.3.3</selenium-webdrivermanager.version>
|
||||
<commons-io.version>2.11.0</commons-io.version>
|
||||
<jetty-server.version>${jetty.version}</jetty-server.version>
|
||||
|
||||
<!-- build plugin management -->
|
||||
<!-- lock down plugins versions to avoid using Maven defaults -->
|
||||
<maven-clean-plugin.version>3.2.0</maven-clean-plugin.version>
|
||||
<maven-dependency-plugin.version>3.5.0</maven-dependency-plugin.version>
|
||||
<maven-resources-plugin.version>3.3.1</maven-resources-plugin.version>
|
||||
<maven-compiler-plugin.version>3.11.0</maven-compiler-plugin.version>
|
||||
<versions-maven-plugin.version>2.15.0</versions-maven-plugin.version>
|
||||
<maven-surefire-plugin.version>3.1.0</maven-surefire-plugin.version>
|
||||
<maven-war-plugin.version>3.3.2</maven-war-plugin.version>
|
||||
<maven-install-plugin.version>3.1.1</maven-install-plugin.version>
|
||||
<maven-deploy-plugin.version>3.1.1</maven-deploy-plugin.version>
|
||||
<maven-site-plugin.version>3.12.1</maven-site-plugin.version>
|
||||
<maven-project-info-reports-plugin.version>3.4.3</maven-project-info-reports-plugin.version>
|
||||
<maven-checkstyle-plugin.version>3.2.2</maven-checkstyle-plugin.version>
|
||||
<checkstyle.version>10.12.0</checkstyle.version>
|
||||
|
||||
<!-- plugins -->
|
||||
<maven-eclipse-plugin.version>2.10</maven-eclipse-plugin.version>
|
||||
<jetty-runner.version>${jetty.version}</jetty-runner.version>
|
||||
<jetty-maven-plugin.version>${jetty.version}</jetty-maven-plugin.version>
|
||||
<duplicate-finder-maven-plugin.version>1.5.1</duplicate-finder-maven-plugin.version>
|
||||
<maven-javadoc-plugin.version>3.5.0</maven-javadoc-plugin.version>
|
||||
<resources-optimizer-maven-plugin.version>2.5.6</resources-optimizer-maven-plugin.version>
|
||||
<fizzed-watcher-maven-plugin.verson>1.0.6</fizzed-watcher-maven-plugin.verson>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>net.sourceforge.plantuml</groupId>
|
||||
<artifactId>plantuml</artifactId>
|
||||
<version>${plantuml.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.webjars.npm</groupId>
|
||||
<artifactId>monaco-editor</artifactId>
|
||||
<version>${monaco-editor.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>apache-jsp</artifactId>
|
||||
<version>${apache-jsp.version}</version>
|
||||
<scope>${apache-jsp.scope}</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-annotations</artifactId>
|
||||
<version>${jetty-annotations.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- jlatexmath -->
|
||||
<dependency>
|
||||
<groupId>org.scilab.forge</groupId>
|
||||
<artifactId>jlatexmath</artifactId>
|
||||
<version>${jlatexmath.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.scilab.forge</groupId>
|
||||
<artifactId>jlatexmath-font-greek</artifactId>
|
||||
<version>${jlatexmath-font-greek.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.scilab.forge</groupId>
|
||||
<artifactId>jlatexmath-font-cyrillic</artifactId>
|
||||
<version>${jlatexmath-font-cyrillic.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<!-- PDF
|
||||
PlantUMLs PDF generation requires:
|
||||
- batik-dom
|
||||
- batik-svgrasterizer (includes batik-dom)
|
||||
- batik-svggen
|
||||
- fop-core
|
||||
-->
|
||||
<dependency>
|
||||
<groupId>org.apache.xmlgraphics</groupId>
|
||||
<artifactId>batik-svgrasterizer</artifactId>
|
||||
<version>${batik.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.xmlgraphics</groupId>
|
||||
<artifactId>batik-svggen</artifactId>
|
||||
<version>${batik.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.xmlgraphics</groupId>
|
||||
<artifactId>fop-core</artifactId>
|
||||
<version>${fop.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Testing -->
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-params</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.platform</groupId>
|
||||
<artifactId>junit-platform-suite-api</artifactId>
|
||||
<version>${junit-suite.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.seleniumhq.selenium</groupId>
|
||||
<artifactId>selenium-java</artifactId>
|
||||
<version>${selenium.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.bonigarcia</groupId>
|
||||
<artifactId>webdrivermanager</artifactId>
|
||||
<version>${selenium-webdrivermanager.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-server</artifactId>
|
||||
<version>${jetty-server.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>plantuml</finalName>
|
||||
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-clean-plugin</artifactId>
|
||||
<version>${maven-clean-plugin.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<version>${maven-dependency-plugin.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>${maven-resources-plugin.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>${maven-compiler-plugin.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${maven-surefire-plugin.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>${maven-war-plugin.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-install-plugin</artifactId>
|
||||
<version>${maven-install-plugin.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<version>${maven-deploy-plugin.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-site-plugin</artifactId>
|
||||
<version>${maven-site-plugin.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-project-info-reports-plugin</artifactId>
|
||||
<version>${maven-project-info-reports-plugin.version}</version>
|
||||
</plugin>
|
||||
<!-- set up java style rules -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<version>${maven-checkstyle-plugin.version}</version>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.puppycrawl.tools</groupId>
|
||||
<artifactId>checkstyle</artifactId>
|
||||
<version>${checkstyle.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<configuration>
|
||||
<configLocation>${basedir}/src/main/config/checkstyle.xml</configLocation>
|
||||
<linkXRef>false</linkXRef>
|
||||
<consoleOutput>true</consoleOutput>
|
||||
<failsOnError>true</failsOnError>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- set up version validation rules -->
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>versions-maven-plugin</artifactId>
|
||||
<version>${versions-maven-plugin.version}</version>
|
||||
<configuration>
|
||||
<outputFile>${project.build.directory}/outdated-dependencies.txt</outputFile>
|
||||
<rulesUri>file:///${basedir}/src/main/config/rules.xml</rulesUri>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
|
||||
<plugins>
|
||||
<!-- set java compile version -->
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>${maven-compiler-plugin.version}</version>
|
||||
<configuration>
|
||||
<source>${maven.compiler.source}</source>
|
||||
<target>${maven.compiler.target}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- configure surefire to skip unit tests if skipTests is set -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${maven-surefire-plugin.version}</version>
|
||||
<configuration>
|
||||
<skipTests>${skipTests}</skipTests>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- configure plugin for project's reports -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-site-plugin</artifactId>
|
||||
<version>${maven-site-plugin.version}</version>
|
||||
</plugin>
|
||||
<!-- setup java style checks -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<version>${maven-checkstyle-plugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<?m2e execute onConfiguration,onIncremental?>
|
||||
<phase>validate</phase>
|
||||
<goals>
|
||||
<goal>check</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<!-- check and display possible version updates during validation
|
||||
manual execution:
|
||||
- mvn versions:display-property-updates
|
||||
- mvn versions:display-dependency-updates
|
||||
-->
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>versions-maven-plugin</artifactId>
|
||||
<version>${versions-maven-plugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>validate</phase>
|
||||
<goals>
|
||||
<goal>display-property-updates</goal>
|
||||
<goal>display-dependency-updates</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<!-- check for duplicate classes/resources
|
||||
also see:
|
||||
- mvn dependency:analyze
|
||||
- mvn dependency:tree
|
||||
-->
|
||||
<plugin>
|
||||
<groupId>org.basepom.maven</groupId>
|
||||
<artifactId>duplicate-finder-maven-plugin</artifactId>
|
||||
<version>${duplicate-finder-maven-plugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>check</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<ignoredResourcePatterns>
|
||||
<ignoredResourcePattern>^about\.html$</ignoredResourcePattern>
|
||||
<ignoredResourcePattern>^license/LICENSE\.dom-software\.txt$</ignoredResourcePattern>
|
||||
<!-- <ignoredResourcePattern>^org/apache/batik/apps/rasterizer/resources/rasterizer\.policy$</ignoredResourcePattern> -->
|
||||
</ignoredResourcePatterns>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- check for missing java documentation -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>${maven-javadoc-plugin.version}</version>
|
||||
<configuration>
|
||||
<show>private</show>
|
||||
<nohelp>true</nohelp>
|
||||
<source>${java.version}</source>
|
||||
<failOnWarnings>true</failOnWarnings>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- provide dependencies -->
|
||||
<plugin>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<version>${maven-dependency-plugin.version}</version>
|
||||
<executions>
|
||||
<!-- provide webjars for the embedded jetty server for junit tests -->
|
||||
<execution>
|
||||
<?m2e execute onConfiguration,onIncremental?>
|
||||
<id>unpack-resources</id>
|
||||
<phase>generate-test-sources</phase>
|
||||
<goals>
|
||||
<goal>unpack</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactItems>
|
||||
<artifactItem>
|
||||
<groupId>org.webjars.npm</groupId>
|
||||
<artifactId>monaco-editor</artifactId>
|
||||
<version>${monaco-editor.version}</version>
|
||||
<includes>**/min/vs/loader.js,**/min/vs/**/*,**/min-maps/vs/**/*</includes>
|
||||
<outputDirectory>${project.build.outputDirectory}</outputDirectory>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
</configuration>
|
||||
</execution>
|
||||
<!-- provide jetty-runner -->
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>copy</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactItems>
|
||||
<artifactItem>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-runner</artifactId>
|
||||
<version>${jetty-runner.version}</version>
|
||||
<destFileName>jetty-runner.jar</destFileName>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<!-- configure eclipse web tools platform (WTP) -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-eclipse-plugin</artifactId>
|
||||
<version>${maven-eclipse-plugin.version}</version>
|
||||
<configuration>
|
||||
<wtpversion>${wtp.version}</wtpversion>
|
||||
<wtpContextName>${wtp.contextName}</wtpContextName>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- configure jetty -->
|
||||
<plugin>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-maven-plugin</artifactId>
|
||||
<version>${jetty-maven-plugin.version}</version>
|
||||
<configuration>
|
||||
<!-- jetty.xml
|
||||
Only necessary to support old proxy.
|
||||
The old proxy needs empty path segments support in URIs.
|
||||
Hence: allow AMBIGUOUS_EMPTY_SEGMENT
|
||||
-->
|
||||
<jettyXmls>${basedir}/src/main/config/jetty.xml</jettyXmls>
|
||||
<scanIntervalSeconds>5</scanIntervalSeconds>
|
||||
<webApp>
|
||||
<contextPath>${jetty.contextpath}</contextPath>
|
||||
</webApp>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- configure java server pages (JSP) web resources -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>${maven-war-plugin.version}</version>
|
||||
<configuration>
|
||||
<webResources>
|
||||
<resource>
|
||||
<directory>${basedir}/src/main/webapp</directory>
|
||||
<includes>
|
||||
<include>*.jspf</include>
|
||||
</includes>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</webResources>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- remove minified web resources (css, js) before regeneration -->
|
||||
<plugin>
|
||||
<artifactId>maven-clean-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>clean-minified-resources</id>
|
||||
<phase>initialize</phase>
|
||||
<goals>
|
||||
<goal>clean</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<excludeDefaultDirectories>true</excludeDefaultDirectories>
|
||||
<filesets>
|
||||
<fileset>
|
||||
<directory>${basedir}/src/main/webapp/min</directory>
|
||||
</fileset>
|
||||
</filesets>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<!-- optimize/minimize web resources (css, js) -->
|
||||
<plugin>
|
||||
<groupId>org.primefaces.extensions</groupId>
|
||||
<artifactId>resources-optimizer-maven-plugin</artifactId>
|
||||
<version>${resources-optimizer-maven-plugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>optimize</id>
|
||||
<phase>generate-resources</phase>
|
||||
<goals>
|
||||
<goal>optimize</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<warningLevel>DEFAULT</warningLevel>
|
||||
<failOnWarning>true</failOnWarning>
|
||||
<suffix>.min</suffix>
|
||||
<languageIn>ECMASCRIPT_2020</languageIn>
|
||||
<languageOut>ECMASCRIPT5_STRICT</languageOut>
|
||||
<emitUseStrict>true</emitUseStrict>
|
||||
<resourcesSets>
|
||||
<!-- combine and optimize all JS files for the web server except the PlantUML JS language features -->
|
||||
<resourcesSet>
|
||||
<inputDir>${basedir}/src/main/webapp</inputDir>
|
||||
<includes>
|
||||
<include>components/**/*.js</include>
|
||||
<include>js/**/*.js</include>
|
||||
</includes>
|
||||
<excludes>
|
||||
<exclude>js/language/**</exclude>
|
||||
</excludes>
|
||||
<aggregations>
|
||||
<aggregation>
|
||||
<withoutCompress>${withoutCSSJSCompress}</withoutCompress>
|
||||
<removeIncluded>false</removeIncluded>
|
||||
<outputFile>${basedir}/src/main/webapp/min/plantuml.min.js</outputFile>
|
||||
</aggregation>
|
||||
</aggregations>
|
||||
</resourcesSet>
|
||||
<!-- combine and optimize all PlantUML JS language features -->
|
||||
<resourcesSet>
|
||||
<inputDir>${basedir}/src/main/webapp/js/language</inputDir>
|
||||
<includes>
|
||||
<include>language.js</include>
|
||||
<include>validation/validation.js</include>
|
||||
<include>**/*.js</include>
|
||||
</includes>
|
||||
<aggregations>
|
||||
<aggregation>
|
||||
<withoutCompress>${withoutCSSJSCompress}</withoutCompress>
|
||||
<removeIncluded>false</removeIncluded>
|
||||
<outputFile>${basedir}/src/main/webapp/min/plantuml-language.min.js</outputFile>
|
||||
</aggregation>
|
||||
</aggregations>
|
||||
</resourcesSet>
|
||||
<!-- combine and optimize all web server style files -->
|
||||
<resourcesSet>
|
||||
<inputDir>${basedir}/src/main/webapp/components</inputDir>
|
||||
<includes>
|
||||
<include>**/*.css</include>
|
||||
</includes>
|
||||
<aggregations>
|
||||
<aggregation>
|
||||
<withoutCompress>${withoutCSSJSCompress}</withoutCompress>
|
||||
<removeIncluded>false</removeIncluded>
|
||||
<outputFile>${basedir}/src/main/webapp/min/plantuml.min.css</outputFile>
|
||||
</aggregation>
|
||||
</aggregations>
|
||||
</resourcesSet>
|
||||
</resourcesSets>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- watch for changes in web resources (css, js) and regenerate minified resources (only for development) -->
|
||||
<plugin>
|
||||
<groupId>com.fizzed</groupId>
|
||||
<artifactId>fizzed-watcher-maven-plugin</artifactId>
|
||||
<version>${fizzed-watcher-maven-plugin.verson}</version>
|
||||
<configuration>
|
||||
<watches>
|
||||
<watch>
|
||||
<directory>${basedir}/src/main/webapp/components</directory>
|
||||
<recursive>true</recursive>
|
||||
<includes>
|
||||
<include>*.js</include>
|
||||
<include>*.css</include>
|
||||
</includes>
|
||||
<excludes>
|
||||
<exclude>*.min.js</exclude>
|
||||
<exclude>*.min.css</exclude>
|
||||
</excludes>
|
||||
</watch>
|
||||
</watches>
|
||||
<goals>
|
||||
<goal>clean:clean@clean-minified-resources</goal>
|
||||
<goal>org.primefaces.extensions:resources-optimizer-maven-plugin:optimize</goal>
|
||||
</goals>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<reporting>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-project-info-reports-plugin</artifactId>
|
||||
<version>${maven-project-info-reports-plugin.version}</version>
|
||||
<reportSets>
|
||||
<reportSet>
|
||||
<reports>
|
||||
<report>index</report>
|
||||
<report>dependencies</report>
|
||||
</reports>
|
||||
</reportSet>
|
||||
</reportSets>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>versions-maven-plugin</artifactId>
|
||||
<version>${versions-maven-plugin.version}</version>
|
||||
<reportSets>
|
||||
<reportSet>
|
||||
<reports>
|
||||
<!-- <report>dependency-updates-report</report> -->
|
||||
<!-- <report>plugin-updates-report</report> -->
|
||||
<report>property-updates-report</report>
|
||||
</reports>
|
||||
</reportSet>
|
||||
</reportSets>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>${maven-javadoc-plugin.version}</version>
|
||||
<reportSets>
|
||||
<reportSet>
|
||||
<id>html</id>
|
||||
<reports>
|
||||
<report>javadoc</report>
|
||||
</reports>
|
||||
</reportSet>
|
||||
</reportSets>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<version>${maven-checkstyle-plugin.version}</version>
|
||||
<reportSets>
|
||||
<reportSet>
|
||||
<reports>
|
||||
<report>checkstyle</report>
|
||||
<report>checkstyle-aggregate</report>
|
||||
</reports>
|
||||
</reportSet>
|
||||
</reportSets>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</reporting>
|
||||
</project>
|
246
pom.xml
|
@ -1,236 +1,22 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||
>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.sourceforge.plantuml</groupId>
|
||||
|
||||
<parent>
|
||||
<groupId>org.sourceforge.plantuml</groupId>
|
||||
<artifactId>plantumlservlet-parent</artifactId>
|
||||
<version>1-SNAPSHOT</version>
|
||||
<relativePath>pom.parent.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>plantumlservlet</artifactId>
|
||||
<version>1-SNAPSHOT</version>
|
||||
<name>PlantUML Servlet</name>
|
||||
<packaging>war</packaging>
|
||||
<build>
|
||||
<finalName>plantuml</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-eclipse-plugin</artifactId>
|
||||
<version>2.8</version>
|
||||
<configuration>
|
||||
<wtpversion>1.5</wtpversion>
|
||||
<wtpContextName>plantuml</wtpContextName>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>2.3.2</version>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.mortbay.jetty</groupId>
|
||||
<artifactId>jetty-maven-plugin</artifactId>
|
||||
<version>${jetty.version}</version>
|
||||
<configuration>
|
||||
<scanIntervalSeconds>5</scanIntervalSeconds>
|
||||
<webApp>
|
||||
<contextPath>${jetty.contextpath}</contextPath>
|
||||
</webApp>
|
||||
<systemProperties>
|
||||
<systemProperty>
|
||||
<name>jetty.port</name>
|
||||
<value>${jetty.port}</value>
|
||||
</systemProperty>
|
||||
</systemProperties>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<version>2.3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals><goal>copy</goal></goals>
|
||||
<configuration>
|
||||
<artifactItems>
|
||||
<artifactItem>
|
||||
<groupId>org.mortbay.jetty</groupId>
|
||||
<artifactId>jetty-runner</artifactId>
|
||||
<version>8.1.9.v20130131</version>
|
||||
<destFileName>jetty-runner.jar</destFileName>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>2.3</version>
|
||||
<configuration>
|
||||
<webResources>
|
||||
<resource>
|
||||
<directory>src/main/webapp</directory>
|
||||
<includes>
|
||||
<include>*.jspf</include>
|
||||
</includes>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</webResources>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.14.1</version>
|
||||
<configuration>
|
||||
<skipTests>true</skipTests>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-site-plugin</artifactId>
|
||||
<version>3.0-beta-3</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<version>2.11</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>validate</id>
|
||||
<phase>validate</phase>
|
||||
<configuration>
|
||||
<configLocation>${basedir}/src/main/config/checkstyle.xml</configLocation>
|
||||
<encoding>UTF-8</encoding>
|
||||
<consoleOutput>true</consoleOutput>
|
||||
<failsOnError>true</failsOnError>
|
||||
<linkXRef>false</linkXRef>
|
||||
</configuration>
|
||||
<goals>
|
||||
<goal>check</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<reporting>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-project-info-reports-plugin</artifactId>
|
||||
<version>2.6</version>
|
||||
<reportSets>
|
||||
<reportSet>
|
||||
<reports><!-- select reports -->
|
||||
<report>index</report>
|
||||
<report>dependencies</report>
|
||||
</reports>
|
||||
</reportSet>
|
||||
</reportSets>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.9.1</version>
|
||||
<configuration>
|
||||
<show>private</show>
|
||||
<nohelp>true</nohelp>
|
||||
</configuration>
|
||||
<reportSets>
|
||||
<reportSet>
|
||||
<id>html</id>
|
||||
<reports>
|
||||
<report>javadoc</report>
|
||||
</reports>
|
||||
</reportSet>
|
||||
</reportSets>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<version>2.11</version>
|
||||
<configuration>
|
||||
<configLocation>${basedir}/src/main/config/checkstyle.xml</configLocation>
|
||||
<encoding>UTF-8</encoding>
|
||||
<linkXRef>false</linkXRef>
|
||||
</configuration>
|
||||
<reportSets>
|
||||
<reportSet>
|
||||
<reports>
|
||||
<report>checkstyle</report>
|
||||
</reports>
|
||||
</reportSet>
|
||||
</reportSets>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</reporting>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<jetty.version>8.0.4.v20111024</jetty.version>
|
||||
<jetty.port>8080</jetty.port>
|
||||
<jetty.contextpath>/plantuml</jetty.contextpath>
|
||||
<maven.build.timestamp.format>yyyyMMdd-HHmm
|
||||
</maven.build.timestamp.format>
|
||||
<timestamp>${maven.build.timestamp}</timestamp>
|
||||
<java.version>11</java.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>net.sourceforge.plantuml</groupId>
|
||||
<artifactId>plantuml</artifactId>
|
||||
<version>1.2018.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>jstl</artifactId>
|
||||
<version>1.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.webjars</groupId>
|
||||
<artifactId>codemirror</artifactId>
|
||||
<version>3.21</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>HTTPClient</groupId>
|
||||
<artifactId>HTTPClient</artifactId>
|
||||
<version>0.3-3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<version>2.5</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>3.8.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>httpunit</groupId>
|
||||
<artifactId>httpunit</artifactId>
|
||||
<version>1.7</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>rhino</groupId>
|
||||
<artifactId>js</artifactId>
|
||||
<version>1.7R2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.aggregate</groupId>
|
||||
<artifactId>jetty-all</artifactId>
|
||||
<version>${jetty.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mortbay.jetty</groupId>
|
||||
<artifactId>jsp-2.1-glassfish</artifactId>
|
||||
<version>2.1.v20100127</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
Before Width: | Height: | Size: 46 KiB |
|
@ -1,126 +1,121 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN" "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
|
||||
|
||||
<!--
|
||||
This configuration file was written by the eclipse-cs plugin configuration editor
|
||||
-->
|
||||
<!--
|
||||
Checkstyle-Configuration: checkstyle
|
||||
Description: none
|
||||
-->
|
||||
<module name="Checker">
|
||||
<property name="severity" value="error"/>
|
||||
<property name="charset" value="UTF-8"/>
|
||||
<module name="TreeWalker">
|
||||
<module name="JavadocMethod">
|
||||
<property name="severity" value="ignore"/>
|
||||
<metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
|
||||
</module>
|
||||
<module name="JavadocType">
|
||||
<property name="severity" value="ignore"/>
|
||||
<metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
|
||||
</module>
|
||||
<module name="JavadocVariable">
|
||||
<property name="severity" value="ignore"/>
|
||||
<metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
|
||||
</module>
|
||||
<module name="JavadocStyle">
|
||||
<property name="severity" value="ignore"/>
|
||||
<metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
|
||||
</module>
|
||||
<module name="ConstantName"/>
|
||||
<module name="LocalFinalVariableName"/>
|
||||
<module name="LocalVariableName"/>
|
||||
<module name="MemberName"/>
|
||||
<module name="MethodName"/>
|
||||
<module name="PackageName"/>
|
||||
<module name="ParameterName"/>
|
||||
<module name="StaticVariableName"/>
|
||||
<module name="TypeName"/>
|
||||
<module name="AvoidStarImport"/>
|
||||
<module name="IllegalImport"/>
|
||||
<module name="RedundantImport"/>
|
||||
<module name="UnusedImports"/>
|
||||
<module name="LineLength">
|
||||
<property name="max" value="120"/>
|
||||
<property name="tabWidth" value="4"/>
|
||||
</module>
|
||||
<module name="MethodLength"/>
|
||||
<module name="ParameterNumber"/>
|
||||
<module name="EmptyForIteratorPad"/>
|
||||
<module name="MethodParamPad"/>
|
||||
<module name="NoWhitespaceAfter"/>
|
||||
<module name="NoWhitespaceBefore"/>
|
||||
<module name="OperatorWrap"/>
|
||||
<module name="ParenPad"/>
|
||||
<module name="TypecastParenPad"/>
|
||||
<module name="WhitespaceAfter"/>
|
||||
<module name="WhitespaceAround"/>
|
||||
<module name="ModifierOrder">
|
||||
<property name="severity" value="ignore"/>
|
||||
<metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
|
||||
</module>
|
||||
<module name="RedundantModifier"/>
|
||||
<module name="AvoidNestedBlocks"/>
|
||||
<module name="EmptyBlock">
|
||||
<property name="severity" value="ignore"/>
|
||||
<metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
|
||||
</module>
|
||||
<module name="LeftCurly"/>
|
||||
<module name="NeedBraces"/>
|
||||
<module name="RightCurly"/>
|
||||
<module name="AvoidInlineConditionals">
|
||||
<property name="severity" value="ignore"/>
|
||||
<metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
|
||||
</module>
|
||||
<module name="EmptyStatement"/>
|
||||
<module name="EqualsHashCode"/>
|
||||
<module name="HiddenField"/>
|
||||
<module name="IllegalInstantiation"/>
|
||||
<module name="InnerAssignment"/>
|
||||
<module name="MagicNumber">
|
||||
<property name="severity" value="ignore"/>
|
||||
<metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
|
||||
</module>
|
||||
<module name="MissingSwitchDefault"/>
|
||||
<module name="RedundantThrows"/>
|
||||
<module name="SimplifyBooleanExpression">
|
||||
<property name="severity" value="ignore"/>
|
||||
<metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
|
||||
</module>
|
||||
<module name="SimplifyBooleanReturn"/>
|
||||
<module name="DesignForExtension">
|
||||
<property name="severity" value="ignore"/>
|
||||
<metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
|
||||
</module>
|
||||
<module name="FinalClass"/>
|
||||
<module name="HideUtilityClassConstructor"/>
|
||||
<module name="InterfaceIsType"/>
|
||||
<module name="VisibilityModifier"/>
|
||||
<module name="ArrayTypeStyle"/>
|
||||
<module name="FinalParameters">
|
||||
<property name="severity" value="ignore"/>
|
||||
<metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
|
||||
</module>
|
||||
<module name="TodoComment"/>
|
||||
<module name="UpperEll"/>
|
||||
<property name="charset" value="UTF-8" />
|
||||
<property name="severity" value="error" />
|
||||
<module name="FileLength" />
|
||||
<module name="FileTabCharacter">
|
||||
<property name="eachLine" value="true" />
|
||||
</module>
|
||||
<module name="JavadocPackage">
|
||||
<property name="severity" value="ignore"/>
|
||||
<property name="allowLegacy" value="true"/>
|
||||
<metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
|
||||
<metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit" />
|
||||
<property name="allowLegacy" value="true" />
|
||||
<property name="severity" value="ignore" />
|
||||
</module>
|
||||
<module name="LineLength">
|
||||
<property name="max" value="120" />
|
||||
<property name="tabWidth" value="4" />
|
||||
<!-- ignore java doc including links, e.g.: `* @see <a href="https://...">PlantUML Code</a>` -->
|
||||
<property name="ignorePattern" value="^\s*(\*|//).*@see\s.*?\shref=.*$"/>
|
||||
</module>
|
||||
<module name="NewlineAtEndOfFile">
|
||||
<property name="severity" value="ignore"/>
|
||||
<metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
|
||||
</module>
|
||||
<module name="Translation"/>
|
||||
<module name="FileLength"/>
|
||||
<module name="FileTabCharacter">
|
||||
<property name="eachLine" value="true"/>
|
||||
<metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit" />
|
||||
<property name="severity" value="ignore" />
|
||||
</module>
|
||||
<module name="RegexpSingleline">
|
||||
<property name="format" value="\s+$"/>
|
||||
<property name="message" value="Line has trailing spaces."/>
|
||||
<property name="format" value="\s+$" />
|
||||
<property name="message" value="Line has trailing spaces." />
|
||||
</module>
|
||||
<module name="Translation" />
|
||||
<module name="SuppressWarningsFilter" />
|
||||
<module name="TreeWalker">
|
||||
<module name="ArrayTypeStyle" />
|
||||
<module name="AvoidInlineConditionals">
|
||||
<metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit" />
|
||||
<property name="severity" value="ignore" />
|
||||
</module>
|
||||
<module name="AvoidNestedBlocks" />
|
||||
<module name="AvoidStarImport" />
|
||||
<module name="ConstantName" />
|
||||
<module name="DesignForExtension">
|
||||
<metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit" />
|
||||
<property name="severity" value="ignore" />
|
||||
</module>
|
||||
<module name="EmptyBlock">
|
||||
<metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit" />
|
||||
<property name="severity" value="ignore" />
|
||||
</module>
|
||||
<module name="EmptyForIteratorPad" />
|
||||
<module name="EmptyStatement" />
|
||||
<module name="EqualsHashCode" />
|
||||
<module name="FinalClass" />
|
||||
<module name="FinalParameters">
|
||||
<metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit" />
|
||||
<property name="severity" value="ignore" />
|
||||
</module>
|
||||
<module name="HiddenField" />
|
||||
<module name="HideUtilityClassConstructor" />
|
||||
<module name="IllegalImport" />
|
||||
<module name="IllegalInstantiation" />
|
||||
<module name="InnerAssignment" />
|
||||
<module name="InterfaceIsType" />
|
||||
<module name="JavadocMethod">
|
||||
<metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit" />
|
||||
<property name="severity" value="ignore" />
|
||||
</module>
|
||||
<module name="JavadocStyle">
|
||||
<metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit" />
|
||||
<property name="severity" value="ignore" />
|
||||
</module>
|
||||
<module name="JavadocType">
|
||||
<metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit" />
|
||||
<property name="severity" value="ignore" />
|
||||
</module>
|
||||
<module name="JavadocVariable">
|
||||
<metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit" />
|
||||
<property name="severity" value="ignore" />
|
||||
</module>
|
||||
<module name="LeftCurly" />
|
||||
<module name="LocalFinalVariableName" />
|
||||
<module name="LocalVariableName" />
|
||||
<module name="MagicNumber">
|
||||
<metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit" />
|
||||
<property name="severity" value="ignore" />
|
||||
</module>
|
||||
<module name="MemberName" />
|
||||
<module name="MethodLength" />
|
||||
<module name="MethodName" />
|
||||
<module name="MethodParamPad" />
|
||||
<module name="MissingSwitchDefault" />
|
||||
<module name="ModifierOrder">
|
||||
<metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit" />
|
||||
<property name="severity" value="ignore" />
|
||||
</module>
|
||||
<module name="NeedBraces" />
|
||||
<module name="NoWhitespaceAfter" />
|
||||
<module name="NoWhitespaceBefore" />
|
||||
<module name="OperatorWrap" />
|
||||
<module name="PackageName" />
|
||||
<module name="ParameterName" />
|
||||
<module name="ParameterNumber" />
|
||||
<module name="ParenPad" />
|
||||
<module name="RedundantImport" />
|
||||
<module name="RedundantModifier" />
|
||||
<module name="RightCurly" />
|
||||
<module name="SimplifyBooleanExpression">
|
||||
<metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit" />
|
||||
<property name="severity" value="ignore" />
|
||||
</module>
|
||||
<module name="SimplifyBooleanReturn" />
|
||||
<module name="StaticVariableName" />
|
||||
<module name="TodoComment" />
|
||||
<module name="TypecastParenPad" />
|
||||
<module name="TypeName" />
|
||||
<module name="UnusedImports" />
|
||||
<module name="UpperEll" />
|
||||
<module name="VisibilityModifier" />
|
||||
<module name="WhitespaceAfter" />
|
||||
<module name="WhitespaceAround" />
|
||||
<module name="SuppressWarningsHolder" />
|
||||
</module>
|
||||
</module>
|
||||
|
|
78
src/main/config/jetty.xml
Normal file
|
@ -0,0 +1,78 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd">
|
||||
|
||||
<!-- =============================================================== -->
|
||||
<!-- Configure a Jetty Server instance with an ID "Server" -->
|
||||
<!-- Other configuration files may also configure the "Server" -->
|
||||
<!-- ID, in which case they are adding configuration to the same -->
|
||||
<!-- instance. If other configuration have a different ID, they -->
|
||||
<!-- will create and configure another instance of Jetty. -->
|
||||
<!-- Consult the javadoc of o.e.j.server.Server for all -->
|
||||
<!-- configuration that may be set here. -->
|
||||
<!-- =============================================================== -->
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
|
||||
<!-- =========================================================== -->
|
||||
<!-- Http Configuration. -->
|
||||
<!-- This is a common configuration instance used by all -->
|
||||
<!-- connectors that can carry HTTP semantics (HTTP, HTTPS, etc.)-->
|
||||
<!-- It configures the non wire protocol aspects of the HTTP -->
|
||||
<!-- semantic. -->
|
||||
<!-- -->
|
||||
<!-- This configuration is only defined here and is used by -->
|
||||
<!-- reference from other XML files such as jetty-http.xml, -->
|
||||
<!-- jetty-https.xml and other configuration files which -->
|
||||
<!-- instantiate the connectors. -->
|
||||
<!-- -->
|
||||
<!-- Consult the javadoc of o.e.j.server.HttpConfiguration -->
|
||||
<!-- for all configuration that may be set here. -->
|
||||
<!-- =========================================================== -->
|
||||
<New id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration">
|
||||
<Set name="secureScheme" property="jetty.httpConfig.secureScheme"/>
|
||||
<Set name="securePort" property="jetty.httpConfig.securePort"/>
|
||||
<Set name="outputBufferSize" property="jetty.httpConfig.outputBufferSize"/>
|
||||
<Set name="outputAggregationSize" property="jetty.httpConfig.outputAggregationSize"/>
|
||||
<Set name="requestHeaderSize" property="jetty.httpConfig.requestHeaderSize"/>
|
||||
<Set name="responseHeaderSize" property="jetty.httpConfig.responseHeaderSize"/>
|
||||
<Set name="sendServerVersion" property="jetty.httpConfig.sendServerVersion"/>
|
||||
<Set name="sendDateHeader"><Property name="jetty.httpConfig.sendDateHeader" default="false"/></Set>
|
||||
<Set name="headerCacheSize" property="jetty.httpConfig.headerCacheSize"/>
|
||||
<Set name="delayDispatchUntilContent" property="jetty.httpConfig.delayDispatchUntilContent"/>
|
||||
<Set name="maxErrorDispatches" property="jetty.httpConfig.maxErrorDispatches"/>
|
||||
<Set name="persistentConnectionsEnabled" property="jetty.httpConfig.persistentConnectionsEnabled"/>
|
||||
<Set name="httpCompliance"><Call class="org.eclipse.jetty.http.HttpCompliance" name="from"><Arg><Property name="jetty.httpConfig.compliance" deprecated="jetty.http.compliance" default="RFC7230"/></Arg></Call></Set>
|
||||
<!-- Changed from "SAFE" to "DEFAULT,AMBIGUOUS_EMPTY_SEGMENT" -->
|
||||
<Set name="uriCompliance"><Call class="org.eclipse.jetty.http.UriCompliance" name="from"><Arg><Property name="jetty.httpConfig.uriCompliance" default="DEFAULT,AMBIGUOUS_EMPTY_SEGMENT"/></Arg></Call></Set>
|
||||
<Set name="requestCookieCompliance"><Call class="org.eclipse.jetty.http.CookieCompliance" name="valueOf"><Arg><Property name="jetty.httpConfig.requestCookieCompliance" default="RFC6265"/></Arg></Call></Set>
|
||||
<Set name="responseCookieCompliance"><Call class="org.eclipse.jetty.http.CookieCompliance" name="valueOf"><Arg><Property name="jetty.httpConfig.responseCookieCompliance" default="RFC6265"/></Arg></Call></Set>
|
||||
<Set name="relativeRedirectAllowed"><Property name="jetty.httpConfig.relativeRedirectAllowed" default="false"/></Set>
|
||||
<Set name="useInputDirectByteBuffers" property="jetty.httpConfig.useInputDirectByteBuffers"/>
|
||||
<Set name="useOutputDirectByteBuffers" property="jetty.httpConfig.useOutputDirectByteBuffers"/>
|
||||
</New>
|
||||
|
||||
<New id="httpConnectionFactory" class="org.eclipse.jetty.server.HttpConnectionFactory">
|
||||
<Arg name="config"><Ref refid="httpConfig" /></Arg>
|
||||
</New>
|
||||
|
||||
<New id="httpConnector" class="org.eclipse.jetty.server.ServerConnector">
|
||||
<Arg name="server"><Ref refid="Server" /></Arg>
|
||||
<Arg name="factories">
|
||||
<Array type="org.eclipse.jetty.server.ConnectionFactory">
|
||||
<Item>
|
||||
<Ref refid="httpConnectionFactory" />
|
||||
</Item>
|
||||
</Array>
|
||||
</Arg>
|
||||
|
||||
<!-- Change host and port according to properties. Default is 0.0.0.0 and 8080. -->
|
||||
<Set name="host"><Property name="jetty.http.host" deprecated="jetty.host" default="0.0.0.0" /></Set>
|
||||
<Set name="port"><Property name="jetty.http.port" deprecated="jetty.port" default="8080" /></Set>
|
||||
</New>
|
||||
|
||||
<!-- =========================================================== -->
|
||||
<!-- Add http Connector -->
|
||||
<!-- =========================================================== -->
|
||||
<Call name="addConnector">
|
||||
<Arg><Ref refid="httpConnector" /></Arg>
|
||||
</Call>
|
||||
</Configure>
|
27
src/main/config/rules.xml
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?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>
|
||||
<ignoreVersion type="regex">(?i).*-dev((?:-?\d+)|(?:\.20\d{6}))?</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>
|
|
@ -0,0 +1,151 @@
|
|||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: https://plantuml.com
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.servlet;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServlet;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import net.sourceforge.plantuml.code.Transcoder;
|
||||
import net.sourceforge.plantuml.code.TranscoderUtil;
|
||||
import net.sourceforge.plantuml.servlet.utility.UrlDataExtractor;
|
||||
|
||||
/**
|
||||
* ASCII encoder and decoder servlet for the webapp.
|
||||
* This servlet encodes the diagram in text format or decodes the compressed diagram string.
|
||||
*/
|
||||
@SuppressWarnings("SERIAL")
|
||||
public class AsciiCoderServlet extends HttpServlet {
|
||||
|
||||
/**
|
||||
* 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\\-\\_]+)");
|
||||
|
||||
/**
|
||||
* Context path from the servlet mapping URL pattern.
|
||||
*
|
||||
* @return servlet context path without leading or tailing slash
|
||||
*/
|
||||
protected String getServletContextPath() {
|
||||
return "coder";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
|
||||
request.setCharacterEncoding("UTF-8");
|
||||
|
||||
final String encodedText = getEncodedTextFromUrl(request);
|
||||
|
||||
String text = "";
|
||||
try {
|
||||
text = getTranscoder().decode(encodedText);
|
||||
} catch (Exception e) {
|
||||
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
response.addHeader("Access-Control-Allow-Origin", "*");
|
||||
response.setContentType("text/plain;charset=UTF-8");
|
||||
response.getWriter().write(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doPost(
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response
|
||||
) throws ServletException, IOException {
|
||||
request.setCharacterEncoding("UTF-8");
|
||||
|
||||
// read textual diagram source from request body
|
||||
final StringBuilder uml = new StringBuilder();
|
||||
try (BufferedReader in = request.getReader()) {
|
||||
String line;
|
||||
while ((line = in.readLine()) != null) {
|
||||
uml.append(line).append('\n');
|
||||
}
|
||||
}
|
||||
|
||||
// encode textual diagram source
|
||||
String encoded = "";
|
||||
try {
|
||||
encoded = getTranscoder().encode(uml.toString());
|
||||
} catch (Exception e) {
|
||||
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
response.addHeader("Access-Control-Allow-Origin", "*");
|
||||
response.setContentType("text/plain;charset=UTF-8");
|
||||
response.getWriter().write(encoded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get PlantUML transcoder.
|
||||
*
|
||||
* @return transcoder instance
|
||||
*/
|
||||
protected Transcoder getTranscoder() {
|
||||
return TranscoderUtil.getDefaultTranscoder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get encoded textual diagram source from URL.
|
||||
*
|
||||
* @param request http request which contains the source URL
|
||||
*
|
||||
* @return if successful encoded textual diagram source from URL; otherwise empty string
|
||||
*
|
||||
* @throws IOException if an input or output exception occurred
|
||||
*/
|
||||
protected String getEncodedTextFromUrl(HttpServletRequest request) throws IOException {
|
||||
// textual diagram source from request URI
|
||||
String url = request.getRequestURI();
|
||||
final String contextpath = "/" + getServletContextPath() + "/";
|
||||
if (url.contains(contextpath) && !url.endsWith(contextpath)) {
|
||||
final String encoded = UrlDataExtractor.getEncodedDiagram(request.getRequestURI(), "");
|
||||
if (!encoded.isEmpty()) {
|
||||
return encoded;
|
||||
}
|
||||
}
|
||||
// textual diagram source from "url" parameter
|
||||
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 url;
|
||||
}
|
||||
// nothing found
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
* Project Info: https://plantuml.com
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
|
@ -25,13 +25,19 @@ package net.sourceforge.plantuml.servlet;
|
|||
|
||||
import net.sourceforge.plantuml.FileFormat;
|
||||
|
||||
/*
|
||||
/**
|
||||
* ASCII servlet of the webapp.
|
||||
* This servlet produces the UML sequence diagram in text format.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
@SuppressWarnings("SERIAL")
|
||||
public class AsciiServlet extends UmlDiagramService {
|
||||
|
||||
/**
|
||||
* Gives the wished output format of the diagram.
|
||||
* This value is used by the DiagramResponse class.
|
||||
*
|
||||
* @return the format for ASCII responses
|
||||
*/
|
||||
@Override
|
||||
public FileFormat getOutputFormat() {
|
||||
return FileFormat.UTXT;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
* Project Info: https://plantuml.com
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
|
@ -23,31 +23,24 @@
|
|||
*/
|
||||
package net.sourceforge.plantuml.servlet;
|
||||
|
||||
import java.io.IOException;
|
||||
import net.sourceforge.plantuml.FileFormat;
|
||||
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/*
|
||||
* Welcome servlet of the webapp.
|
||||
* Displays the sample Bob and Alice sequence diagram.
|
||||
/**
|
||||
* Base64 servlet of the webapp.
|
||||
* This servlet produces the UML diagram in Base64 format.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class Welcome extends HttpServlet {
|
||||
@SuppressWarnings("SERIAL")
|
||||
public class Base64Servlet extends UmlDiagramService {
|
||||
|
||||
/**
|
||||
* Gives the wished output format of the diagram.
|
||||
* This value is used by the DiagramResponse class.
|
||||
*
|
||||
* @return the format for Base64 responses
|
||||
*/
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
|
||||
|
||||
// set the sample
|
||||
request.setAttribute("decoded", "Bob -> Alice : hello");
|
||||
request.setAttribute("encoded", "SyfFKj2rKt3CoKnELR1Io4ZDoSa70000");
|
||||
|
||||
// forward to index.jsp
|
||||
RequestDispatcher dispatcher = request.getRequestDispatcher("/index.jsp");
|
||||
dispatcher.forward(request, response);
|
||||
public FileFormat getOutputFormat() {
|
||||
return FileFormat.BASE64;
|
||||
}
|
||||
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
* Project Info: https://plantuml.com
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
|
@ -26,47 +26,45 @@ package net.sourceforge.plantuml.servlet;
|
|||
import java.io.IOException;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServlet;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import net.sourceforge.plantuml.FileFormat;
|
||||
|
||||
import net.sourceforge.plantuml.servlet.utility.UmlExtractor;
|
||||
import net.sourceforge.plantuml.servlet.utility.UrlDataExtractor;
|
||||
|
||||
/*
|
||||
/**
|
||||
* Check servlet of the webapp.
|
||||
* This servlet checks the syntax of the diagram and send a report in TEXT format.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
@SuppressWarnings("SERIAL")
|
||||
public class CheckSyntaxServlet extends HttpServlet {
|
||||
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
|
||||
|
||||
// build the UML source from the compressed request parameter
|
||||
String uml = UmlExtractor.getUmlSource(getSource(request.getRequestURI()));
|
||||
final String url = request.getRequestURI();
|
||||
final String uml = UmlExtractor.getUmlSource(UrlDataExtractor.getEncodedDiagram(url, ""));
|
||||
|
||||
// generate the response
|
||||
DiagramResponse dr = new DiagramResponse(response, getOutputFormat(), request);
|
||||
try {
|
||||
dr.sendCheck(uml);
|
||||
} catch (IIOException iioe) {
|
||||
} catch (IIOException e) {
|
||||
// Browser has closed the connection, do nothing
|
||||
}
|
||||
dr = null;
|
||||
}
|
||||
|
||||
public String getSource(String uri) {
|
||||
String[] result = uri.split("/check/", 2);
|
||||
if (result.length != 2) {
|
||||
return "";
|
||||
} else {
|
||||
return result[1];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives the wished output format of the diagram.
|
||||
* This value is used by the DiagramResponse class.
|
||||
*
|
||||
* @return the format for check responses
|
||||
*/
|
||||
public FileFormat getOutputFormat() {
|
||||
return FileFormat.UTXT;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
* Project Info: https://plantuml.com
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
|
@ -23,71 +23,254 @@
|
|||
*/
|
||||
package net.sourceforge.plantuml.servlet;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import net.sourceforge.plantuml.BlockUml;
|
||||
import net.sourceforge.plantuml.ErrorUml;
|
||||
import net.sourceforge.plantuml.FileFormat;
|
||||
import net.sourceforge.plantuml.FileFormatOption;
|
||||
import net.sourceforge.plantuml.NullOutputStream;
|
||||
import net.sourceforge.plantuml.SourceStringReader;
|
||||
import net.sourceforge.plantuml.StringUtils;
|
||||
import net.sourceforge.plantuml.core.DiagramDescription;
|
||||
import net.sourceforge.plantuml.utils.Base64Coder;
|
||||
import net.sourceforge.plantuml.core.Diagram;
|
||||
import net.sourceforge.plantuml.core.DiagramDescription;
|
||||
import net.sourceforge.plantuml.core.ImageData;
|
||||
import net.sourceforge.plantuml.error.PSystemError;
|
||||
import net.sourceforge.plantuml.preproc.Defines;
|
||||
import net.sourceforge.plantuml.security.SecurityProfile;
|
||||
import net.sourceforge.plantuml.security.SecurityUtils;
|
||||
import net.sourceforge.plantuml.version.Version;
|
||||
import net.sourceforge.plantuml.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.
|
||||
*/
|
||||
class DiagramResponse {
|
||||
public class DiagramResponse {
|
||||
|
||||
private static class BlockSelection {
|
||||
private final BlockUml block;
|
||||
private final int systemIdx;
|
||||
|
||||
BlockSelection(BlockUml blk, int idx) {
|
||||
block = blk;
|
||||
systemIdx = idx;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
/**
|
||||
* PLANTUML_CONFIG_FILE content.
|
||||
*/
|
||||
private static final List<String> CONFIG = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Cache/flag to ensure that the `init()` method is called only once.
|
||||
*/
|
||||
private static boolean initialized = false;
|
||||
|
||||
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");
|
||||
CONTENT_TYPE = Collections.unmodifiableMap(map);
|
||||
init();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void sendDiagram(String uml, int idx) throws IOException {
|
||||
/**
|
||||
* Initialize PlantUML configurations and properties as well as loading the PlantUML config file.
|
||||
*/
|
||||
public static void init() {
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
initialized = true;
|
||||
// set headless mode manually since otherwise Windows 11 seems to have some issues with it
|
||||
// see Issue#311 :: https://github.com/plantuml/plantuml-server/issues/311
|
||||
// NOTE: This can only be set before any awt/X11/... related stuff is loaded
|
||||
System.setProperty("java.awt.headless", System.getProperty("java.awt.headless", "true"));
|
||||
// set security profile to INTERNET by default
|
||||
// NOTE: this property is cached inside PlantUML and cannot be changed after the first call of PlantUML
|
||||
System.setProperty("PLANTUML_SECURITY_PROFILE", SecurityProfile.INTERNET.toString());
|
||||
if (System.getenv("PLANTUML_SECURITY_PROFILE") != null) {
|
||||
System.setProperty("PLANTUML_SECURITY_PROFILE", System.getenv("PLANTUML_SECURITY_PROFILE"));
|
||||
}
|
||||
// load properties from file
|
||||
if (System.getenv("PLANTUML_PROPERTY_FILE") != null) {
|
||||
try (FileReader propertyFileReader = new FileReader(System.getenv("PLANTUML_PROPERTY_FILE"))) {
|
||||
System.getProperties().load(propertyFileReader);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
// load PlantUML config file
|
||||
if (System.getenv("PLANTUML_CONFIG_FILE") != null) {
|
||||
try (BufferedReader br = new BufferedReader(new FileReader(System.getenv("PLANTUML_CONFIG_FILE")))) {
|
||||
br.lines().forEach(CONFIG::add);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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());
|
||||
SourceStringReader reader = new SourceStringReader(uml);
|
||||
final BlockUml blockUml = reader.getBlocks().get(0);
|
||||
if (notModified(blockUml)) {
|
||||
addHeaderForCache(blockUml);
|
||||
|
||||
if (idx < 0) {
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST, String.format("Invalid diagram index: {0}", idx));
|
||||
return;
|
||||
}
|
||||
final SourceStringReader reader = getSourceStringReader(uml);
|
||||
if (reader == null) {
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "No UML diagram found");
|
||||
return;
|
||||
}
|
||||
|
||||
if (format == FileFormat.BASE64) {
|
||||
byte[] imageBytes;
|
||||
try (ByteArrayOutputStream outstream = new ByteArrayOutputStream()) {
|
||||
reader.outputImage(outstream, idx, new FileFormatOption(FileFormat.PNG));
|
||||
imageBytes = outstream.toByteArray();
|
||||
}
|
||||
final String base64 = Base64Coder.encodeLines(imageBytes).replaceAll("\\s", "");
|
||||
final String encodedBytes = "data:image/png;base64," + base64;
|
||||
response.getOutputStream().write(encodedBytes.getBytes());
|
||||
return;
|
||||
}
|
||||
|
||||
final BlockSelection blockSelection = getOutputBlockSelection(reader, idx);
|
||||
if (blockSelection == null) {
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
|
||||
return;
|
||||
}
|
||||
|
||||
if (notModified(blockSelection.block)) {
|
||||
addHeaderForCache(blockSelection.block);
|
||||
response.sendError(HttpServletResponse.SC_NOT_MODIFIED);
|
||||
return;
|
||||
}
|
||||
if (StringUtils.isDiagramCacheable(uml)) {
|
||||
addHeaderForCache(blockUml);
|
||||
addHeaderForCache(blockSelection.block);
|
||||
}
|
||||
reader.outputImage(response.getOutputStream(), new FileFormatOption(format, false));
|
||||
final Diagram diagram = blockSelection.block.getDiagram();
|
||||
if (diagram instanceof PSystemError) {
|
||||
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
||||
}
|
||||
diagram.exportDiagram(response.getOutputStream(), blockSelection.systemIdx, new FileFormatOption(format));
|
||||
}
|
||||
|
||||
private BlockSelection getOutputBlockSelection(SourceStringReader reader, int numImage) {
|
||||
if (numImage < 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Collection<BlockUml> blocks = reader.getBlocks();
|
||||
if (blocks.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (BlockUml b : blocks) {
|
||||
final Diagram system = b.getDiagram();
|
||||
final int nbInSystem = system.getNbImages();
|
||||
if (numImage < nbInSystem) {
|
||||
return new BlockSelection(b, numImage);
|
||||
}
|
||||
numImage -= nbInSystem;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private SourceStringReader getSourceStringReader(String uml) {
|
||||
SourceStringReader reader = getSourceStringReaderWithConfig(uml);
|
||||
if (reader.getBlocks().isEmpty()) {
|
||||
uml = "@startuml\n" + uml + "\n@enduml";
|
||||
reader = getSourceStringReaderWithConfig(uml);
|
||||
if (reader.getBlocks().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return reader;
|
||||
}
|
||||
|
||||
private SourceStringReader getSourceStringReaderWithConfig(String uml) {
|
||||
final Defines defines = getPreProcDefines();
|
||||
SourceStringReader reader = new SourceStringReader(defines, uml, CONFIG);
|
||||
if (!CONFIG.isEmpty() && reader.getBlocks().get(0).getDiagram().getWarningOrError() != null) {
|
||||
reader = new SourceStringReader(defines, uml);
|
||||
}
|
||||
return reader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get PlantUML preprocessor defines.
|
||||
*
|
||||
* @return preprocessor defines
|
||||
*/
|
||||
private Defines getPreProcDefines() {
|
||||
final Defines defines;
|
||||
if (SecurityUtils.getSecurityProfile() == SecurityProfile.UNSECURE) {
|
||||
// set dirpath to current dir but keep filename and filenameNoExtension undefined
|
||||
defines = Defines.createWithFileName(new java.io.File("dummy.puml"));
|
||||
defines.overrideFilename("");
|
||||
} else {
|
||||
defines = Defines.createEmpty();
|
||||
}
|
||||
return defines;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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");
|
||||
|
@ -101,32 +284,75 @@ class DiagramResponse {
|
|||
return ifNoneMatch.contains(etag);
|
||||
}
|
||||
|
||||
|
||||
void sendMap(String uml) throws IOException {
|
||||
/**
|
||||
* Produce and send the image map of the uml diagram in HTML format.
|
||||
*
|
||||
* @param uml textual UML diagram source
|
||||
* @param idx diagram index of {@code uml} to send
|
||||
*
|
||||
* @throws IOException if an input or output exception occurred
|
||||
*/
|
||||
public void sendMap(String uml, int idx) throws IOException {
|
||||
response.addHeader("Access-Control-Allow-Origin", "*");
|
||||
response.setContentType(getContentType());
|
||||
SourceStringReader reader = new SourceStringReader(uml);
|
||||
final BlockUml blockUml = reader.getBlocks().get(0);
|
||||
if (StringUtils.isDiagramCacheable(uml)) {
|
||||
addHeaderForCache(blockUml);
|
||||
|
||||
if (idx < 0) {
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST, String.format("Invalid diagram index: {0}", idx));
|
||||
return;
|
||||
}
|
||||
final Diagram diagram = blockUml.getDiagram();
|
||||
ImageData map = diagram.exportDiagram(new NullOutputStream(), 0,
|
||||
new FileFormatOption(FileFormat.PNG, false));
|
||||
final SourceStringReader reader = getSourceStringReader(uml);
|
||||
if (reader == null) {
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "No UML diagram found");
|
||||
return;
|
||||
}
|
||||
final BlockSelection blockSelection = getOutputBlockSelection(reader, idx);
|
||||
if (blockSelection == null) {
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
|
||||
return;
|
||||
}
|
||||
|
||||
if (StringUtils.isDiagramCacheable(uml)) {
|
||||
addHeaderForCache(blockSelection.block);
|
||||
}
|
||||
final Diagram diagram = blockSelection.block.getDiagram();
|
||||
if (diagram instanceof PSystemError) {
|
||||
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
||||
}
|
||||
ImageData map = diagram.exportDiagram(
|
||||
new NullOutputStream(),
|
||||
blockSelection.systemIdx,
|
||||
new FileFormatOption(FileFormat.PNG, false)
|
||||
);
|
||||
if (map.containsCMapData()) {
|
||||
PrintWriter httpOut = response.getWriter();
|
||||
final String cmap = map.getCMapData("plantuml");
|
||||
httpOut.print(cmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sendCheck(String uml) throws IOException {
|
||||
/**
|
||||
* 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
|
||||
|
@ -150,15 +376,24 @@ class DiagramResponse {
|
|||
addHeaders(response);
|
||||
}
|
||||
|
||||
public static void addHeaders(HttpServletResponse response) {
|
||||
/**
|
||||
* Add default headers to response.
|
||||
*
|
||||
* @param response http response
|
||||
*/
|
||||
private static void addHeaders(HttpServletResponse response) {
|
||||
response.addHeader("X-Powered-By", POWERED_BY);
|
||||
response.addHeader("X-Patreon", "Support us on http://plantuml.com/patreon");
|
||||
response.addHeader("X-Donate", "http://plantuml.com/paypal");
|
||||
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);
|
||||
return format.getMimeType();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
* Project Info: https://plantuml.com
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
|
@ -25,13 +25,19 @@ package net.sourceforge.plantuml.servlet;
|
|||
|
||||
import net.sourceforge.plantuml.FileFormat;
|
||||
|
||||
/*
|
||||
/**
|
||||
* EPS servlet of the webapp.
|
||||
* This servlet produces the UML diagram in EPS format.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
@SuppressWarnings("SERIAL")
|
||||
public class EpsServlet extends UmlDiagramService {
|
||||
|
||||
/**
|
||||
* Gives the wished output format of the diagram.
|
||||
* This value is used by the DiagramResponse class.
|
||||
*
|
||||
* @return the format for EPS responses
|
||||
*/
|
||||
@Override
|
||||
public FileFormat getOutputFormat() {
|
||||
return FileFormat.EPS;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
* Project Info: https://plantuml.com
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
|
@ -25,13 +25,19 @@ package net.sourceforge.plantuml.servlet;
|
|||
|
||||
import net.sourceforge.plantuml.FileFormat;
|
||||
|
||||
/*
|
||||
* EPS servlet of the webapp.
|
||||
* This servlet produces the UML diagram in EPS format.
|
||||
/**
|
||||
* EPS Text servlet of the webapp.
|
||||
* This servlet produces the UML diagram in EPS Text format.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
@SuppressWarnings("SERIAL")
|
||||
public class EpsTextServlet extends UmlDiagramService {
|
||||
|
||||
/**
|
||||
* Gives the wished output format of the diagram.
|
||||
* This value is used by the DiagramResponse class.
|
||||
*
|
||||
* @return the format for EPS Text responses
|
||||
*/
|
||||
@Override
|
||||
public FileFormat getOutputFormat() {
|
||||
return FileFormat.EPS_TEXT;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
* Project Info: https://plantuml.com
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
|
@ -25,13 +25,19 @@ package net.sourceforge.plantuml.servlet;
|
|||
|
||||
import net.sourceforge.plantuml.FileFormat;
|
||||
|
||||
/*
|
||||
/**
|
||||
* Image servlet of the webapp.
|
||||
* This servlet produces the UML diagram in PNG format.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
@SuppressWarnings("SERIAL")
|
||||
public class ImgServlet extends UmlDiagramService {
|
||||
|
||||
/**
|
||||
* Gives the wished output format of the diagram.
|
||||
* This value is used by the DiagramResponse class.
|
||||
*
|
||||
* @return the format for image responses
|
||||
*/
|
||||
@Override
|
||||
public FileFormat getOutputFormat() {
|
||||
return FileFormat.PNG;
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: https://plantuml.com
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.servlet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServlet;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import net.sourceforge.plantuml.syntax.LanguageDescriptor;
|
||||
|
||||
/**
|
||||
* Servlet used to inspect the language keywords of the running PlantUML server.
|
||||
* Same as {@code java -jar plantuml.jar -language}
|
||||
*/
|
||||
public class LanguageServlet extends HttpServlet {
|
||||
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
throw new ServletException(new UnsupportedOperationException("The Language servlet only handles GET requests"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
final PrintStream ps = new PrintStream(response.getOutputStream());
|
||||
response.setContentType("text/text");
|
||||
new LanguageDescriptor().print(ps);
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
* Project Info: https://plantuml.com
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
|
@ -26,47 +26,46 @@ package net.sourceforge.plantuml.servlet;
|
|||
import java.io.IOException;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServlet;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import net.sourceforge.plantuml.FileFormat;
|
||||
|
||||
import net.sourceforge.plantuml.servlet.utility.UmlExtractor;
|
||||
import net.sourceforge.plantuml.servlet.utility.UrlDataExtractor;
|
||||
|
||||
/*
|
||||
/**
|
||||
* MAP servlet of the webapp.
|
||||
* This servlet produces the image map of the diagram in HTML format.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
@SuppressWarnings("SERIAL")
|
||||
public class MapServlet extends HttpServlet {
|
||||
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
|
||||
|
||||
// build the UML source from the compressed request parameter
|
||||
String uml = UmlExtractor.getUmlSource(getSource(request.getRequestURI()));
|
||||
final String url = request.getRequestURI();
|
||||
final String uml = UmlExtractor.getUmlSource(UrlDataExtractor.getEncodedDiagram(url, ""));
|
||||
final int idx = UrlDataExtractor.getIndex(url, 0);
|
||||
|
||||
// generate the response
|
||||
DiagramResponse dr = new DiagramResponse(response, getOutputFormat(), request);
|
||||
try {
|
||||
dr.sendMap(uml);
|
||||
} catch (IIOException iioe) {
|
||||
dr.sendMap(uml, idx);
|
||||
} catch (IIOException e) {
|
||||
// Browser has closed the connection, do nothing
|
||||
}
|
||||
dr = null;
|
||||
}
|
||||
|
||||
public String getSource(String uri) {
|
||||
String[] result = uri.split("/map/", 2);
|
||||
if (result.length != 2) {
|
||||
return "";
|
||||
} else {
|
||||
return result[1];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives the wished output format of the diagram.
|
||||
* This value is used by the DiagramResponse class.
|
||||
*
|
||||
* @return the format for map responses
|
||||
*/
|
||||
public FileFormat getOutputFormat() {
|
||||
return FileFormat.UTXT;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,376 @@
|
|||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: https://plantuml.com
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.servlet;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.annotation.MultipartConfig;
|
||||
import jakarta.servlet.http.HttpServlet;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.Part;
|
||||
import net.sourceforge.plantuml.FileFormat;
|
||||
import net.sourceforge.plantuml.code.NoPlantumlCompressionException;
|
||||
import net.sourceforge.plantuml.code.TranscoderUtil;
|
||||
import net.sourceforge.plantuml.json.JsonObject;
|
||||
import net.sourceforge.plantuml.klimt.drawing.svg.SvgGraphics;
|
||||
import net.sourceforge.plantuml.png.MetadataTag;
|
||||
|
||||
/**
|
||||
* Meta data servlet for the webapp.
|
||||
* This servlet responses with the meta data of a specific file as text report or JSON object.
|
||||
*/
|
||||
@SuppressWarnings("SERIAL")
|
||||
@MultipartConfig
|
||||
public class MetadataServlet extends HttpServlet {
|
||||
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
|
||||
request.setCharacterEncoding("UTF-8");
|
||||
final String urlString = request.getParameter("src");
|
||||
// validate URL
|
||||
final URL url = ProxyServlet.validateURL(urlString, response);
|
||||
if (url == null) {
|
||||
return; // error is already set/handled inside `validateURL`
|
||||
}
|
||||
// fetch image via URL and extract meta data from it
|
||||
final HttpURLConnection conn = ProxyServlet.getConnection(url);
|
||||
try (InputStream is = conn.getInputStream()) {
|
||||
handleRequest(request, response, is, conn.getContentType(), null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doPost(
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response
|
||||
) throws IOException, ServletException {
|
||||
request.setCharacterEncoding("UTF-8");
|
||||
// get image via file upload
|
||||
final Part filePart = request.getPart("diagram");
|
||||
final String filename = Paths.get(filePart.getSubmittedFileName()).getFileName().toString(); // MS IE fix
|
||||
try (InputStream is = filePart.getInputStream()) {
|
||||
handleRequest(request, response, is, null, filename);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle request no matter whether GET or POST and
|
||||
* response with the PlantUML diagram image in the in the desired format if possible.
|
||||
*
|
||||
* @param request an HttpServletRequest object that contains the request the client has made of the servlet
|
||||
* @param response an HttpServletResponse object that contains the response the servlet sends to the client
|
||||
* @param is PlantUML diagram image as input stream
|
||||
* @param contentType the PlantUML diagram image content type [optional]
|
||||
* @param filename the PlantUML diagram image filename [optional
|
||||
*
|
||||
* @throws IOException if an input or output error is detected when the servlet handles the request
|
||||
*/
|
||||
private void handleRequest(
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
InputStream is,
|
||||
String contentType,
|
||||
String filename
|
||||
) throws IOException {
|
||||
final String formString = request.getParameter("format");
|
||||
final String accept = request.getHeader("Accept");
|
||||
final boolean isJsonResponse = accept != null && accept.toLowerCase().contains("json");
|
||||
// extract meta data
|
||||
// @see <a href="https://github.com/plantuml/plantuml/blob/26874fe610617738f958b7e8d012128fe621cff6/src/net/sourceforge/plantuml/Run.java#L570-L592">PlantUML Code</a>
|
||||
final FileFormat format = getImageFileFormat(formString, contentType, filename, response);
|
||||
if (format == null) {
|
||||
return; // error is already set/handled inside `getImageFileFormat`
|
||||
}
|
||||
final Metadata metadata = getMetadata(is, format, response);
|
||||
if (metadata == null) {
|
||||
return; // error is already set/handled inside `getMetadata`
|
||||
}
|
||||
response.addHeader("Access-Control-Allow-Origin", "*");
|
||||
if (isJsonResponse) {
|
||||
response.setContentType("application/json;charset=UTF-8");
|
||||
response.getWriter().write(metadata.toJson().toString());
|
||||
} else {
|
||||
response.setContentType(FileFormat.UTXT.getMimeType());
|
||||
response.getWriter().write(metadata.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file format from the PlantUML diagram image.
|
||||
*
|
||||
* @param format image format passed by the user via the request param `format`
|
||||
* @param contentType response content type where the PlantUML diagram image is from
|
||||
* @param filename diagram image file name
|
||||
* @param response response object to `sendError` including error message
|
||||
*
|
||||
* @return PlantUML diagram image format; if unknown format return `null`
|
||||
*
|
||||
* @throws IOException `response.sendError` can result in a `IOException`
|
||||
*/
|
||||
private FileFormat getImageFileFormat(
|
||||
String format, String contentType, String filename, HttpServletResponse response
|
||||
) throws IOException {
|
||||
if (format != null && !format.isEmpty()) {
|
||||
return getImageFileFormatFromFormatString(format, response);
|
||||
}
|
||||
if (filename != null && !filename.isEmpty()) {
|
||||
final FileFormat fileFormat = getImageFileFormatFromFilenameExtension(filename);
|
||||
if (fileFormat != null) {
|
||||
return fileFormat;
|
||||
}
|
||||
}
|
||||
if (contentType != null && !contentType.isEmpty()) {
|
||||
final FileFormat fileFormat = getImageFileFormatFromContentType(contentType);
|
||||
if (fileFormat != null) {
|
||||
return fileFormat;
|
||||
}
|
||||
}
|
||||
response.sendError(
|
||||
HttpServletResponse.SC_BAD_REQUEST,
|
||||
"PlantUML image format detection failed. Please set \"format\" (format) manually."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file format from the PlantUML diagram image based on a format string.
|
||||
*
|
||||
* @param format image format passed by the user via the request param `format`
|
||||
* @param response response object to `sendError` including error message; if `null` no error will be send
|
||||
*
|
||||
* @return PlantUML diagram image format; if unknown format return `null`
|
||||
*
|
||||
* @throws IOException `response.sendError` can result in a `IOException`
|
||||
*/
|
||||
private FileFormat getImageFileFormatFromFormatString(
|
||||
String format, HttpServletResponse response
|
||||
) throws IOException {
|
||||
switch (format.toLowerCase()) {
|
||||
case "png": return FileFormat.PNG;
|
||||
case "svg": return FileFormat.SVG;
|
||||
default:
|
||||
if (response != null) {
|
||||
response.sendError(
|
||||
HttpServletResponse.SC_BAD_REQUEST,
|
||||
"The format \"" + format + "\" is not supported for meta data extraction."
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file format from the PlantUML diagram image based on the filenames extension.
|
||||
*
|
||||
* @param filename PlantUML image file name
|
||||
*
|
||||
* @return PlantUML diagram image format; if unknown format return `null`
|
||||
*
|
||||
* @throws IOException Can not happend! Will not occur.
|
||||
*/
|
||||
private FileFormat getImageFileFormatFromFilenameExtension(String filename) throws IOException {
|
||||
int extensionPosition = filename.lastIndexOf(".");
|
||||
if (extensionPosition != -1) {
|
||||
String extension = filename.substring(extensionPosition + 1);
|
||||
return getImageFileFormatFromFormatString(extension, null);
|
||||
}
|
||||
Logger logger = Logger.getLogger("com.plantuml");
|
||||
logger.log(Level.WARNING, "File name \"{0}\" is malformed. Should be: name.extension", filename);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file format from the PlantUML diagram image based on the response content type.
|
||||
*
|
||||
* @param contentType response content type where the PlantUML diagram image is from
|
||||
*
|
||||
* @return PlantUML diagram image format; if unknown content type return `null`
|
||||
*/
|
||||
private FileFormat getImageFileFormatFromContentType(String contentType) {
|
||||
final String ct = contentType.toLowerCase();
|
||||
if (ct.contains("png")) {
|
||||
return FileFormat.PNG;
|
||||
}
|
||||
if (ct.contains("svg") || ct.contains("xml")) {
|
||||
return FileFormat.SVG;
|
||||
}
|
||||
Logger logger = Logger.getLogger("com.plantuml");
|
||||
logger.log(Level.SEVERE, "Unknown content type \"{0}\" for meta data extraction", contentType);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get meta data from PlantUML diagram image.
|
||||
*
|
||||
* @param is PlantUML diagram image input stream
|
||||
* @param format PlantUML diagram image file format
|
||||
* @param response response object to `sendError` including error message
|
||||
*
|
||||
* @return parsed meta data; on error return `null`
|
||||
*
|
||||
* @throws IOException `response.sendError` can result in a `IOException`
|
||||
*/
|
||||
private Metadata getMetadata(
|
||||
InputStream is, FileFormat format, HttpServletResponse response
|
||||
) throws IOException {
|
||||
switch (format) {
|
||||
case PNG:
|
||||
return getMetadataFromPNG(is, response);
|
||||
case SVG:
|
||||
final String svg;
|
||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
|
||||
svg = br.lines().collect(Collectors.joining("\n"));
|
||||
}
|
||||
return getMetadataFromSVG(svg, response);
|
||||
default:
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Unsupported image format.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get meta data from PNG PlantUML diagram image.
|
||||
*
|
||||
* Challenge: PNG meta data is only a single String and contains more than the PlantUML diagram.
|
||||
* PNG meta data contains:
|
||||
* 1. decoded PlantUML code
|
||||
* 2. empty line
|
||||
* 3. version information
|
||||
* Notes:
|
||||
* - in theory the meta data could contain the PlantUML `RawString` as well as the `PlainString`
|
||||
* but since both are ALWAYS identical (methods to get them are identical), one will ALWAYS dropped.
|
||||
* @see <a href="https://github.com/plantuml/plantuml/blob/26874fe610617738f958b7e8d012128fe621cff6/src/net/sourceforge/plantuml/core/UmlSource.java#L173-L189">PlantUML Code</a>
|
||||
* - version information do not contain any empty lines
|
||||
* Solution: split meta data at the last occurring empty line the result in
|
||||
* a. decoded PlantUML diagram
|
||||
* b. version information
|
||||
*
|
||||
* @param is PNG image input stream
|
||||
* @param response response object to `sendError` including error message
|
||||
*
|
||||
* @return parsed meta data; on error return `null`
|
||||
*
|
||||
* @throws IOException `response.sendError` can result in a `IOException`
|
||||
*/
|
||||
private Metadata getMetadataFromPNG(InputStream is, HttpServletResponse response) throws IOException {
|
||||
final String rawMetadata = new MetadataTag(is, "plantuml").getData();
|
||||
if (rawMetadata == null) {
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "No meta data found.");
|
||||
return null;
|
||||
}
|
||||
// parse meta data
|
||||
final Metadata metadata = new Metadata(rawMetadata.trim());
|
||||
metadata.decoded = metadata.rawContent.substring(0, metadata.rawContent.lastIndexOf("\n\n"));
|
||||
metadata.encoded = TranscoderUtil.getDefaultTranscoder().encode(metadata.decoded);
|
||||
metadata.version = metadata.rawContent.substring(rawMetadata.lastIndexOf("\n\n")).trim();
|
||||
// add additionally the encoded plantuml string to raw meta data since it's missing by default
|
||||
metadata.rawContent = metadata.encoded + "\n\n" + metadata.rawContent;
|
||||
return metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get meta data from SVG PlantUML diagram image.
|
||||
* @see <a href="https://github.com/plantuml/plantuml/blob/26874fe610617738f958b7e8d012128fe621cff6/src/net/sourceforge/plantuml/Run.java#L574-L587">PlantUML Code</a>
|
||||
*
|
||||
* @param svg PlantUML digram in SVG format
|
||||
* @param response response object to `sendError` including error message
|
||||
*
|
||||
* @return parsed meta data; on error return `null`
|
||||
*
|
||||
* @throws IOException `response.sendError` can result in a `IOException`
|
||||
*/
|
||||
private Metadata getMetadataFromSVG(String svg, HttpServletResponse response) throws IOException {
|
||||
final Metadata metadata = new Metadata();
|
||||
// search for meta data start token
|
||||
final int idx = svg.lastIndexOf(SvgGraphics.META_HEADER);
|
||||
if (idx == -1) {
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "No meta data found.");
|
||||
return null;
|
||||
}
|
||||
// search for meta data end token
|
||||
final String part = svg.substring(idx + SvgGraphics.META_HEADER.length());
|
||||
final int idxEnd = part.indexOf("]");
|
||||
if (idxEnd == -1) {
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid meta data: No end token found.");
|
||||
return null;
|
||||
}
|
||||
// parse meta data
|
||||
metadata.encoded = part.substring(0, idxEnd);
|
||||
try {
|
||||
metadata.decoded = TranscoderUtil.getDefaultTranscoderProtected().decode(metadata.encoded);
|
||||
} catch (NoPlantumlCompressionException ex) {
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid meta data: PlantUML diagram is corrupted.");
|
||||
return null;
|
||||
}
|
||||
return metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class to store meta data.
|
||||
*/
|
||||
@SuppressWarnings("checkstyle:VisibilityModifier")
|
||||
private class Metadata {
|
||||
public String rawContent;
|
||||
public String decoded;
|
||||
public String encoded;
|
||||
public String version;
|
||||
|
||||
Metadata() { }
|
||||
Metadata(String rawMetadataContent) {
|
||||
rawContent = rawMetadataContent;
|
||||
}
|
||||
|
||||
public JsonObject toJson() {
|
||||
JsonObject metadata = new JsonObject();
|
||||
metadata.add("encoded", encoded);
|
||||
metadata.add("decoded", decoded);
|
||||
if (version != null && !version.isEmpty()) {
|
||||
metadata.add("version", version);
|
||||
}
|
||||
return metadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (rawContent != null && !rawContent.isEmpty()) {
|
||||
return rawContent;
|
||||
}
|
||||
if (version == null || version.isEmpty()) {
|
||||
return encoded + "\n\n" + decoded;
|
||||
}
|
||||
return encoded + "\n\n" + decoded + "\n\n" + version;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
* Project Info: https://plantuml.com
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
|
@ -23,87 +23,118 @@
|
|||
*/
|
||||
package net.sourceforge.plantuml.servlet;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import HTTPClient.CookieModule;
|
||||
import HTTPClient.HTTPConnection;
|
||||
import HTTPClient.HTTPResponse;
|
||||
import HTTPClient.ModuleException;
|
||||
import HTTPClient.ParseException;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServlet;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import net.sourceforge.plantuml.FileFormat;
|
||||
import net.sourceforge.plantuml.FileFormatOption;
|
||||
import net.sourceforge.plantuml.SourceStringReader;
|
||||
|
||||
/*
|
||||
/**
|
||||
* Proxy servlet of the webapp.
|
||||
* This servlet retrieves the diagram source of a web resource (web html page)
|
||||
* and renders it.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
@SuppressWarnings("SERIAL")
|
||||
public class OldProxyServlet extends HttpServlet {
|
||||
|
||||
private static final Pattern PROXY_PATTERN = Pattern.compile("/\\w+/proxy/((\\d+)/)?((\\w+)/)?(http://.*)");
|
||||
private String format;
|
||||
/**
|
||||
* Proxy request URI regex pattern.
|
||||
*/
|
||||
private static final Pattern PROXY_PATTERN = Pattern.compile("/\\w+/proxy/((\\d+)/)?((\\w+)/)?(https?://[^@]*)");
|
||||
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
|
||||
|
||||
final String uri = request.getRequestURI();
|
||||
|
||||
// Check if the src URL is valid
|
||||
Matcher proxyMatcher = PROXY_PATTERN.matcher(uri);
|
||||
if (proxyMatcher.matches()) {
|
||||
String num = proxyMatcher.group(2); // Optional number of the diagram source
|
||||
format = proxyMatcher.group(4); // Expected format of the generated diagram
|
||||
String sourceURL = proxyMatcher.group(5);
|
||||
handleImageProxy(response, num, sourceURL);
|
||||
} else {
|
||||
request.setAttribute("net.sourceforge.plantuml.servlet.decoded", "ERROR Invalid proxy syntax : " + uri);
|
||||
request.removeAttribute("net.sourceforge.plantuml.servlet.encoded");
|
||||
|
||||
// forward to index.jsp
|
||||
RequestDispatcher dispatcher = request.getRequestDispatcher("/index.jsp");
|
||||
dispatcher.forward(request, response);
|
||||
if (!proxyMatcher.matches()) {
|
||||
// Bad URI format.
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "URL malformed.");
|
||||
return;
|
||||
}
|
||||
|
||||
String num = proxyMatcher.group(2); // Optional number of the diagram source
|
||||
String format = proxyMatcher.group(4); // Expected format of the generated diagram
|
||||
String sourceURL = proxyMatcher.group(5);
|
||||
if (ProxyServlet.forbiddenURL(sourceURL)) {
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Forbidden URL format.");
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
reader.generateImage(response.getOutputStream(), n, new FileFormatOption(getOutputFormat(), false));
|
||||
FileFormat fileFormat = getOutputFormat(format);
|
||||
response.addHeader("Content-Type", fileFormat.getMimeType());
|
||||
reader.outputImage(response.getOutputStream(), n, new FileFormatOption(fileFormat, false));
|
||||
}
|
||||
|
||||
private String getSource(String uri) throws IOException {
|
||||
CookieModule.setCookiePolicyHandler(null);
|
||||
|
||||
final Pattern p = Pattern.compile("http://[^/]+(/?.*)");
|
||||
final Matcher m = p.matcher(uri);
|
||||
if (m.find() == false) {
|
||||
throw new IOException(uri);
|
||||
}
|
||||
/**
|
||||
* 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);
|
||||
final HTTPConnection httpConnection = new HTTPConnection(url);
|
||||
try {
|
||||
final HTTPResponse resp = httpConnection.Get(m.group(1));
|
||||
return resp.getText();
|
||||
} catch (ModuleException e) {
|
||||
throw new IOException(e.toString());
|
||||
} catch (ParseException e) {
|
||||
throw new IOException(e.toString());
|
||||
try (
|
||||
InputStream responseStream = url.openStream();
|
||||
InputStreamReader isr = new InputStreamReader(responseStream);
|
||||
BufferedReader br = new BufferedReader(isr);
|
||||
) {
|
||||
String line;
|
||||
StringBuffer sb = new StringBuffer();
|
||||
while ((line = br.readLine()) != null) {
|
||||
sb.append(line);
|
||||
sb.append("\n");
|
||||
}
|
||||
return sb.toString().trim();
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: https://plantuml.com
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.servlet;
|
||||
|
||||
import net.sourceforge.plantuml.FileFormat;
|
||||
|
||||
/**
|
||||
* PDF servlet of the webapp.
|
||||
* This servlet produces the UML diagram in PDF format.
|
||||
*/
|
||||
@SuppressWarnings("SERIAL")
|
||||
public class PdfServlet extends UmlDiagramService {
|
||||
|
||||
/**
|
||||
* Gives the wished output format of the diagram.
|
||||
* This value is used by the DiagramResponse class.
|
||||
*
|
||||
* @return the format for pdf responses
|
||||
*/
|
||||
@Override
|
||||
public FileFormat getOutputFormat() {
|
||||
return FileFormat.PDF;
|
||||
}
|
||||
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
* Project Info: https://plantuml.com
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
|
@ -27,24 +27,22 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import jakarta.servlet.RequestDispatcher;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import net.sourceforge.plantuml.api.PlantumlUtils;
|
||||
import net.sourceforge.plantuml.code.Transcoder;
|
||||
import net.sourceforge.plantuml.code.TranscoderUtil;
|
||||
import net.sourceforge.plantuml.code.NoPlantumlCompressionException;
|
||||
import net.sourceforge.plantuml.png.MetadataTag;
|
||||
import net.sourceforge.plantuml.servlet.utility.Configuration;
|
||||
import net.sourceforge.plantuml.servlet.utility.UmlExtractor;
|
||||
import net.sourceforge.plantuml.servlet.utility.UrlDataExtractor;
|
||||
|
||||
/*
|
||||
* Original idea from Achim Abeling for Confluence macro
|
||||
* See http://www.banapple.de/display/BANAPPLE/plantuml+user+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.
|
||||
|
@ -52,118 +50,270 @@ import net.sourceforge.plantuml.png.MetadataTag;
|
|||
* Modified by Arnaud Roques
|
||||
* Modified by Pablo Lalloni
|
||||
* Modified by Maxime Sinclair
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class PlantUmlServlet extends HttpServlet {
|
||||
@SuppressWarnings("SERIAL")
|
||||
public class PlantUmlServlet extends AsciiCoderServlet {
|
||||
|
||||
static {
|
||||
// Initialize the PlantUML server.
|
||||
// You could say that this is like the `static void main(String[] args)` of the PlantUML server.
|
||||
DiagramResponse.init();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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\\-\\_]+)");
|
||||
@Override
|
||||
protected String getServletContextPath() {
|
||||
return "uml";
|
||||
}
|
||||
|
||||
private static final Pattern RECOVER_UML_PATTERN = Pattern.compile("/uml/(.*)");
|
||||
/**
|
||||
* Encode arbitrary string to HTML string.
|
||||
*
|
||||
* @param string arbitrary string
|
||||
*
|
||||
* @return html encoded string
|
||||
*/
|
||||
public static String stringToHTMLString(String string) {
|
||||
final StringBuilder sb = new StringBuilder(string.length());
|
||||
// true if last char was blank
|
||||
final int length = string.length();
|
||||
int offset = 0;
|
||||
while (offset < length) {
|
||||
final int c = string.codePointAt(offset);
|
||||
if (c == ' ') {
|
||||
sb.append(' ');
|
||||
} else if (c == '"') {
|
||||
sb.append(""");
|
||||
} else if (c == '&') {
|
||||
sb.append("&");
|
||||
} else if (c == '<') {
|
||||
sb.append("<");
|
||||
} else if (c == '>') {
|
||||
sb.append(">");
|
||||
} else if (c == '\r') {
|
||||
sb.append("\r");
|
||||
} else if (c == '\n') {
|
||||
sb.append("\n");
|
||||
} else {
|
||||
int ci = 0xffffff & c;
|
||||
if (ci < 160) {
|
||||
// nothing special only 7 Bit
|
||||
sb.append((char) c);
|
||||
} else {
|
||||
// Not 7 Bit use the unicode system
|
||||
sb.append("&#");
|
||||
sb.append(ci);
|
||||
sb.append(';');
|
||||
}
|
||||
}
|
||||
offset += Character.charCount(c);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
|
||||
request.setCharacterEncoding("UTF-8");
|
||||
String text = request.getParameter("text");
|
||||
|
||||
String metadata = request.getParameter("metadata");
|
||||
if (metadata != null) {
|
||||
InputStream img = null;
|
||||
try {
|
||||
img = getImage(new URL(metadata));
|
||||
MetadataTag metadataTag = new MetadataTag(img, "plantuml");
|
||||
String data = metadataTag.getData();
|
||||
if (data != null) {
|
||||
text = data;
|
||||
}
|
||||
} finally {
|
||||
if (img != null) {
|
||||
img.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
text = getTextFromUrl(request, text);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// textual diagram source
|
||||
final String text = getText(request).trim();
|
||||
|
||||
// no Text form has been submitted
|
||||
if (text == null || text.trim().isEmpty()) {
|
||||
if (text.isEmpty()) {
|
||||
redirectNow(request, response, DEFAULT_ENCODED_TEXT);
|
||||
return;
|
||||
}
|
||||
|
||||
final String encoded = getTranscoder().encode(text);
|
||||
request.setAttribute("decoded", text);
|
||||
request.setAttribute("encoded", encoded);
|
||||
// diagram index to render
|
||||
final int idx = UrlDataExtractor.getIndex(request.getRequestURI());
|
||||
|
||||
// check if an image map is necessary
|
||||
if (text != null && PlantumlUtils.hasCMapData(text)) {
|
||||
request.setAttribute("mapneeded", Boolean.TRUE);
|
||||
}
|
||||
// forward to index.jsp
|
||||
final RequestDispatcher dispatcher = request.getRequestDispatcher("/index.jsp");
|
||||
final String path;
|
||||
final String view = request.getParameter("view");
|
||||
if (view != null && view.equalsIgnoreCase("previewer")) {
|
||||
path = "/previewer.jsp";
|
||||
} else {
|
||||
path = "/index.jsp";
|
||||
}
|
||||
prepareRequestForDispatch(request, text, idx);
|
||||
final RequestDispatcher dispatcher = request.getRequestDispatcher(path);
|
||||
dispatcher.forward(request, response);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
|
||||
IOException {
|
||||
protected void doPost(
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response
|
||||
) throws ServletException, IOException {
|
||||
request.setCharacterEncoding("UTF-8");
|
||||
|
||||
String text = request.getParameter("text");
|
||||
String encoded = DEFAULT_ENCODED_TEXT;
|
||||
// diagram index to render
|
||||
final int idx = UrlDataExtractor.getIndex(request.getRequestURI());
|
||||
|
||||
// encoded diagram source
|
||||
String encoded;
|
||||
try {
|
||||
text = getTextFromUrl(request, text);
|
||||
String text = getText(request).trim();
|
||||
encoded = getTranscoder().encode(text);
|
||||
} catch (Exception e) {
|
||||
encoded = DEFAULT_ENCODED_TEXT;
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
redirectNow(request, response, encoded);
|
||||
redirectNow(request, response, encoded, idx);
|
||||
}
|
||||
|
||||
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()));
|
||||
// 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);
|
||||
/**
|
||||
* Get textual diagram.
|
||||
* Search for textual diagram in following order:
|
||||
* 1. URL {@link PlantUmlServlet.getTextFromUrl}
|
||||
* 2. metadata
|
||||
* 3. request parameter "text"
|
||||
*
|
||||
* @param request http request
|
||||
*
|
||||
* @return if successful textual diagram source; otherwise empty string
|
||||
*
|
||||
* @throws IOException if an input or output exception occurred
|
||||
*/
|
||||
private String getText(final HttpServletRequest request) throws IOException {
|
||||
String text;
|
||||
// 1. URL
|
||||
try {
|
||||
text = getTextFromUrl(request);
|
||||
if (text != null && !text.isEmpty()) {
|
||||
return text;
|
||||
}
|
||||
text = getTranscoder().decode(url);
|
||||
} catch (NoPlantumlCompressionException e) {
|
||||
// no textual diagram source available from Url
|
||||
// ignore and try 2. method (metadata) below
|
||||
// do not spam output console
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return text;
|
||||
// 2. metadata
|
||||
String metadata = request.getParameter("metadata");
|
||||
if (metadata != null) {
|
||||
try (InputStream img = getImage(new URL(metadata))) {
|
||||
MetadataTag metadataTag = new MetadataTag(img, "plantuml");
|
||||
String data = metadataTag.getData();
|
||||
if (data != null) {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 3. request parameter text
|
||||
text = request.getParameter("text");
|
||||
if (text != null && !text.isEmpty()) {
|
||||
return text;
|
||||
}
|
||||
// nothing found
|
||||
return "";
|
||||
}
|
||||
|
||||
private void redirectNow(HttpServletRequest request, HttpServletResponse response, String encoded)
|
||||
throws IOException {
|
||||
final String result = request.getContextPath() + "/uml/" + encoded;
|
||||
response.sendRedirect(result);
|
||||
/**
|
||||
* Get textual diagram source from URL.
|
||||
*
|
||||
* @param request http request which contains the source URL
|
||||
*
|
||||
* @return if successful textual diagram source from URL; otherwise empty string
|
||||
*
|
||||
* @throws IOException if an input or output exception occurred
|
||||
*/
|
||||
private String getTextFromUrl(HttpServletRequest request) throws IOException {
|
||||
return getTranscoder().decode(getEncodedTextFromUrl(request));
|
||||
}
|
||||
|
||||
private Transcoder getTranscoder() {
|
||||
return TranscoderUtil.getDefaultTranscoder();
|
||||
/**
|
||||
* Prepare request for dispatch and get request dispatcher.
|
||||
*
|
||||
* @param request http request which will be further prepared for dispatch
|
||||
* @param text textual diagram source
|
||||
*
|
||||
* @throws IOException if an input or output exception occurred
|
||||
*/
|
||||
private void prepareRequestForDispatch(HttpServletRequest request, String text, int idx) throws IOException {
|
||||
final String encoded = getTranscoder().encode(text);
|
||||
// diagram sources
|
||||
request.setAttribute("encoded", encoded);
|
||||
request.setAttribute("decoded", text);
|
||||
request.setAttribute("index", (idx < 0) ? "" : idx);
|
||||
// properties
|
||||
request.setAttribute("showSocialButtons", Configuration.get("SHOW_SOCIAL_BUTTONS"));
|
||||
request.setAttribute("showGithubRibbon", Configuration.get("SHOW_GITHUB_RIBBON"));
|
||||
// map for diagram source if necessary
|
||||
String map = "";
|
||||
if (PlantumlUtils.hasCMapData(text)) {
|
||||
try {
|
||||
map = UmlExtractor.extractMap(text);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
request.setAttribute("map", map);
|
||||
}
|
||||
|
||||
static private HttpURLConnection getConnection(URL url) 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 {
|
||||
redirectNow(request, response, encoded, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send redirect response to encoded uml text.
|
||||
*
|
||||
* @param request http request
|
||||
* @param response http response
|
||||
* @param encoded encoded uml text
|
||||
* @param index diagram index
|
||||
*
|
||||
* @throws IOException if an input or output exception occurred
|
||||
*/
|
||||
private void redirectNow(
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
String encoded,
|
||||
Integer index
|
||||
) throws IOException {
|
||||
final String path;
|
||||
if (index == null || index < 0) {
|
||||
path = request.getContextPath() + "/uml/" + encoded;
|
||||
} else {
|
||||
path = request.getContextPath() + "/uml/" + index + "/" + encoded;
|
||||
}
|
||||
response.sendRedirect(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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");
|
||||
con.setReadTimeout(10000); // 10 seconds
|
||||
// printHttpsCert(con);
|
||||
con.connect();
|
||||
return con;
|
||||
} else {
|
||||
|
@ -175,13 +325,20 @@ 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();
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,202 @@
|
|||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: https://plantuml.com
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.servlet;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.xml.XMLConstants;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.OutputKeys;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServlet;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import net.sourceforge.plantuml.FileFormat;
|
||||
import net.sourceforge.plantuml.emoji.data.Dummy;
|
||||
import net.sourceforge.plantuml.json.Json;
|
||||
import net.sourceforge.plantuml.json.JsonArray;
|
||||
import net.sourceforge.plantuml.theme.ThemeUtils;
|
||||
import net.sourceforge.plantuml.openiconic.data.DummyIcon;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Small PlantUML frontend or UI helper.
|
||||
*/
|
||||
@SuppressWarnings("SERIAL")
|
||||
public class PlantUmlUIHelperServlet extends HttpServlet {
|
||||
|
||||
private interface HelperConsumer {
|
||||
void accept(HttpServletRequest request, HttpServletResponse response) throws IOException;
|
||||
}
|
||||
|
||||
private final Map<String, HelperConsumer> helpers = new HashMap<>();
|
||||
private String svgIconsSpriteCache = null;
|
||||
|
||||
public PlantUmlUIHelperServlet() {
|
||||
// add all supported request items/helper methods
|
||||
helpers.put("emojis", this::sendEmojis);
|
||||
helpers.put("icons.svg", this::sendIconsSprite);
|
||||
helpers.put("icons", this::sendIcons);
|
||||
helpers.put("themes", this::sendThemes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||
request.setCharacterEncoding("UTF-8");
|
||||
|
||||
final String requestItem = request.getParameter("request");
|
||||
final HelperConsumer requestHelper = this.helpers.get(requestItem);
|
||||
String errorMsg = null;
|
||||
if (requestItem == null) {
|
||||
errorMsg = "Request item not set.";
|
||||
} else if (requestHelper == null) {
|
||||
errorMsg = "Unknown requested item: " + requestItem;
|
||||
}
|
||||
if (errorMsg != null) {
|
||||
setDefaultHeader(response, FileFormat.UTXT);
|
||||
response.getWriter().write(errorMsg);
|
||||
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
||||
return;
|
||||
}
|
||||
|
||||
requestHelper.accept(request, response);
|
||||
}
|
||||
|
||||
private void setDefaultHeader(HttpServletResponse response, FileFormat fileFormat) {
|
||||
setDefaultHeader(response, fileFormat.getMimeType());
|
||||
}
|
||||
|
||||
private HttpServletResponse setDefaultHeader(HttpServletResponse response, String contentType) {
|
||||
response.addHeader("Access-Control-Allow-Origin", "*");
|
||||
response.setContentType(contentType);
|
||||
return response;
|
||||
}
|
||||
|
||||
private void sendJson(HttpServletResponse response, String json) throws IOException {
|
||||
setDefaultHeader(response, "application/json;charset=UTF-8");
|
||||
response.getWriter().write(json);
|
||||
}
|
||||
|
||||
private String[] getIcons() throws IOException {
|
||||
InputStream in = DummyIcon.class.getResourceAsStream("all.txt");
|
||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(in))) {
|
||||
return br.lines().toArray(String[]::new);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendIcons(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||
sendJson(response, Json.array(getIcons()).toString());
|
||||
}
|
||||
|
||||
private void sendIconsSprite(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||
if (svgIconsSpriteCache == null) {
|
||||
// NOTE: all icons has the following svg tag attributes: width="8" height="8" viewBox="0 0 8 8"
|
||||
String[] iconNames = getIcons();
|
||||
StringBuilder sprite = new StringBuilder();
|
||||
sprite.append("<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"8\" height=\"8\" viewBox=\"0 0 8 8\">\n");
|
||||
sprite.append("<defs>\n");
|
||||
sprite.append(" <style><![CDATA[\n");
|
||||
sprite.append(" .sprite { display: none; }\n");
|
||||
sprite.append(" .sprite:target { display: inline; }\n");
|
||||
sprite.append(" ]]></style>\n");
|
||||
sprite.append("</defs>\n");
|
||||
for (String name : iconNames) {
|
||||
try (InputStream in = DummyIcon.class.getResourceAsStream(name + ".svg")) {
|
||||
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
|
||||
docFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
|
||||
docFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
|
||||
DocumentBuilder db = docFactory.newDocumentBuilder();
|
||||
Document doc = db.parse(in);
|
||||
|
||||
Writer out = new StringWriter();
|
||||
out.write("<g class=\"sprite\" id=\"" + name + "\">");
|
||||
|
||||
TransformerFactory tfFactory = TransformerFactory.newInstance();
|
||||
tfFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
|
||||
tfFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
|
||||
Transformer tf = tfFactory.newTransformer();
|
||||
tf.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
|
||||
tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
|
||||
tf.setOutputProperty(OutputKeys.INDENT, "no");
|
||||
NodeList svgInnerNodes = doc.getElementsByTagName("svg").item(0).getChildNodes();
|
||||
for (int index = 0; index < svgInnerNodes.getLength(); index++) {
|
||||
tf.transform(new DOMSource(svgInnerNodes.item(index)), new StreamResult(out));
|
||||
}
|
||||
|
||||
out.write("</g>");
|
||||
sprite.append(out.toString() + "\n");
|
||||
} catch (ParserConfigurationException | SAXException | TransformerException ex) {
|
||||
// skip icons which can not be parsed/read
|
||||
Logger logger = Logger.getLogger("com.plantuml");
|
||||
logger.log(Level.WARNING, "SVG icon \"{0}\" could not be parsed. Skip!", name);
|
||||
}
|
||||
}
|
||||
sprite.append("</svg>\n");
|
||||
svgIconsSpriteCache = sprite.toString();
|
||||
}
|
||||
setDefaultHeader(response, FileFormat.SVG);
|
||||
response.getWriter().write(svgIconsSpriteCache);
|
||||
}
|
||||
|
||||
private String[][] getEmojis() throws IOException {
|
||||
InputStream in = Dummy.class.getResourceAsStream("emoji.txt");
|
||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(in))) {
|
||||
return br.lines().map(line -> line.split(";")).toArray(String[][]::new);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendEmojis(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||
String[][] emojis = getEmojis();
|
||||
JsonArray json = new JsonArray();
|
||||
for (String[] emojiUnicodeNamePair : emojis) {
|
||||
json.add(Json.array(emojiUnicodeNamePair));
|
||||
}
|
||||
sendJson(response, json.toString());
|
||||
}
|
||||
|
||||
private void sendThemes(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||
String[] themes = ThemeUtils.getAllThemeNames().toArray(new String[0]);
|
||||
sendJson(response, Json.array(themes).toString());
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
* Project Info: https://plantuml.com
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
|
@ -29,154 +29,170 @@ import java.io.InputStreamReader;
|
|||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import net.sourceforge.plantuml.BlockUml;
|
||||
import net.sourceforge.plantuml.FileFormat;
|
||||
import net.sourceforge.plantuml.SourceStringReader;
|
||||
import net.sourceforge.plantuml.core.Diagram;
|
||||
import net.sourceforge.plantuml.core.UmlSource;
|
||||
|
||||
import java.security.cert.Certificate;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLPeerUnverifiedException;
|
||||
|
||||
/*
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServlet;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import net.sourceforge.plantuml.FileFormat;
|
||||
|
||||
/**
|
||||
* Proxy servlet of the webapp.
|
||||
* This servlet retrieves the diagram source of a web resource (web html page)
|
||||
* and renders it.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
@SuppressWarnings("SERIAL")
|
||||
public class ProxyServlet extends HttpServlet {
|
||||
|
||||
public static boolean forbiddenURL(String full) {
|
||||
if (full == null) {
|
||||
return true;
|
||||
}
|
||||
if (full.contains("@")) {
|
||||
return true;
|
||||
}
|
||||
if (full.startsWith("https://") == false && full.startsWith("http://") == false) {
|
||||
return true;
|
||||
}
|
||||
if (full.matches("^https?://[-#.0-9:\\[\\]+]+/.*")) {
|
||||
return true;
|
||||
}
|
||||
if (full.matches("^https?://[^.]+/.*")) {
|
||||
return true;
|
||||
}
|
||||
if (full.matches("^https?://[^.]+$")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate external URL.
|
||||
*
|
||||
* @param url URL to validate
|
||||
* @param response response object to `sendError` including error message; if `null` no error will be send
|
||||
*
|
||||
* @return valid URL; otherwise `null`
|
||||
*
|
||||
* @throws IOException `response.sendError` can result in a `IOException`
|
||||
*/
|
||||
public static URL validateURL(String url, HttpServletResponse response) throws IOException {
|
||||
final URL parsedUrl;
|
||||
try {
|
||||
parsedUrl = new URL(url);
|
||||
} catch (MalformedURLException mue) {
|
||||
if (response != null) {
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "URL malformed.");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
// Check if URL is in a forbidden format (e.g. IP-Address)
|
||||
if (forbiddenURL(url)) {
|
||||
if (response != null) {
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Forbidden URL format.");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return parsedUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
|
||||
|
||||
final String fmt = request.getParameter("fmt");
|
||||
final String source = request.getParameter("src");
|
||||
final String index = request.getParameter("idx");
|
||||
final URL srcUrl;
|
||||
// Check if the src URL is valid
|
||||
try {
|
||||
srcUrl = new URL(source);
|
||||
} catch (MalformedURLException mue) {
|
||||
mue.printStackTrace();
|
||||
return;
|
||||
|
||||
final int idx = index == null ? 0 : Integer.parseInt(index);
|
||||
final URL srcUrl = validateURL(source, response);
|
||||
if (srcUrl == null) {
|
||||
return; // error is already set/handled inside `validateURL`
|
||||
}
|
||||
|
||||
// generate the response
|
||||
String diagmarkup = getSource(srcUrl);
|
||||
SourceStringReader reader = new SourceStringReader(diagmarkup);
|
||||
int n = index == null ? 0 : Integer.parseInt(index);
|
||||
List<BlockUml> blocks = reader.getBlocks();
|
||||
BlockUml block = blocks.get(n);
|
||||
Diagram diagram = block.getDiagram();
|
||||
UmlSource umlSrc = diagram.getSource();
|
||||
String uml = umlSrc.getPlainString();
|
||||
//System.out.println("uml=" + uml);
|
||||
// fetch diagram from URL
|
||||
final String uml = getSource(srcUrl);
|
||||
|
||||
// generate the response
|
||||
DiagramResponse dr = new DiagramResponse(response, getOutputFormat(fmt), request);
|
||||
try {
|
||||
dr.sendDiagram(uml, 0);
|
||||
} catch (IIOException iioe) {
|
||||
// special handling for the MAP since it's not using "#sendDiagram()" like the other types
|
||||
if ("map".equals(fmt)) {
|
||||
dr.sendMap(uml, idx);
|
||||
} else {
|
||||
dr.sendDiagram(uml, idx);
|
||||
}
|
||||
} catch (IIOException e) {
|
||||
// Browser has closed the connection, so the HTTP OutputStream is closed
|
||||
// Silently catch the exception to avoid annoying log
|
||||
}
|
||||
dr = null;
|
||||
}
|
||||
|
||||
private String getSource(final URL url) throws IOException {
|
||||
String line;
|
||||
BufferedReader rd;
|
||||
StringBuilder sb;
|
||||
try {
|
||||
HttpURLConnection con = getConnection(url);
|
||||
rd = new BufferedReader(new InputStreamReader(con.getInputStream()));
|
||||
sb = new StringBuilder();
|
||||
|
||||
while ((line = rd.readLine()) != null) {
|
||||
sb.append(line + '\n');
|
||||
}
|
||||
rd.close();
|
||||
return sb.toString();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
rd = null;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private FileFormat getOutputFormat(String format) {
|
||||
if (format == null) {
|
||||
return FileFormat.PNG;
|
||||
}
|
||||
if (format.equals("svg")) {
|
||||
return FileFormat.SVG;
|
||||
}
|
||||
if (format.equals("eps")) {
|
||||
return FileFormat.EPS;
|
||||
}
|
||||
if (format.equals("epstext")) {
|
||||
return FileFormat.EPS_TEXT;
|
||||
}
|
||||
if (format.equals("txt")) {
|
||||
return FileFormat.UTXT;
|
||||
}
|
||||
return FileFormat.PNG;
|
||||
}
|
||||
|
||||
private HttpURLConnection getConnection(final URL url) throws IOException {
|
||||
if (url.getProtocol().startsWith("https")) {
|
||||
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
|
||||
con.setRequestMethod("GET");
|
||||
con.setReadTimeout(10000); // 10 seconds
|
||||
// printHttpsCert(con);
|
||||
con.connect();
|
||||
return con;
|
||||
} else {
|
||||
HttpURLConnection con = (HttpURLConnection) url.openConnection();
|
||||
con.setRequestMethod("GET");
|
||||
con.setReadTimeout(10000); // 10 seconds
|
||||
con.connect();
|
||||
return con;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Debug method used to dump the certificate info
|
||||
* @param con the https connection
|
||||
* 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
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private void printHttpsCert(final HttpsURLConnection con) {
|
||||
if (con != null) {
|
||||
try {
|
||||
System.out.println("Response Code : " + con.getResponseCode());
|
||||
System.out.println("Cipher Suite : " + con.getCipherSuite());
|
||||
System.out.println("\n");
|
||||
|
||||
Certificate[] certs = con.getServerCertificates();
|
||||
for (Certificate cert : certs) {
|
||||
System.out.println("Cert Type : " + cert.getType());
|
||||
System.out.println("Cert Hash Code : " + cert.hashCode());
|
||||
System.out.println("Cert Public Key Algorithm : " + cert.getPublicKey().getAlgorithm());
|
||||
System.out.println("Cert Public Key Format : " + cert.getPublicKey().getFormat());
|
||||
System.out.println("\n");
|
||||
}
|
||||
|
||||
} catch (SSLPeerUnverifiedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
private String getSource(final URL url) throws IOException {
|
||||
HttpURLConnection conn = getConnection(url);
|
||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
|
||||
return br.lines().collect(Collectors.joining("\n"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
switch (format.toLowerCase()) {
|
||||
case "png": return FileFormat.PNG;
|
||||
case "svg": return FileFormat.SVG;
|
||||
case "eps": return FileFormat.EPS;
|
||||
case "epstext": return FileFormat.EPS_TEXT;
|
||||
case "txt": return FileFormat.UTXT;
|
||||
case "map": return FileFormat.UTXT;
|
||||
case "pdf": return FileFormat.PDF;
|
||||
default: 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
|
||||
*/
|
||||
public static HttpURLConnection getConnection(final URL url) throws IOException {
|
||||
final HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setRequestMethod("GET");
|
||||
String token = System.getenv("HTTP_AUTHORIZATION");
|
||||
if (token != null) {
|
||||
conn.setRequestProperty("Authorization", token);
|
||||
}
|
||||
final String timeoutString = System.getenv("HTTP_PROXY_READ_TIMEOUT");
|
||||
int timeout = 10000; // 10 seconds as default
|
||||
if (timeoutString != null && timeoutString.matches("^\\d+$")) {
|
||||
timeout = Integer.parseInt(timeoutString);
|
||||
}
|
||||
conn.setReadTimeout(timeout);
|
||||
conn.connect();
|
||||
return conn;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
* Project Info: https://plantuml.com
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
|
@ -25,13 +25,19 @@ package net.sourceforge.plantuml.servlet;
|
|||
|
||||
import net.sourceforge.plantuml.FileFormat;
|
||||
|
||||
/*
|
||||
/**
|
||||
* SVG servlet of the webapp.
|
||||
* This servlet produces the UML diagram in SVG format.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
@SuppressWarnings("SERIAL")
|
||||
public class SvgServlet extends UmlDiagramService {
|
||||
|
||||
/**
|
||||
* Gives the wished output format of the diagram.
|
||||
* This value is used by the DiagramResponse class.
|
||||
*
|
||||
* @return the format for svg responses
|
||||
*/
|
||||
@Override
|
||||
public FileFormat getOutputFormat() {
|
||||
return FileFormat.SVG;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
* Project Info: https://plantuml.com
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
|
@ -23,77 +23,85 @@
|
|||
*/
|
||||
package net.sourceforge.plantuml.servlet;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServlet;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import net.sourceforge.plantuml.FileFormat;
|
||||
import net.sourceforge.plantuml.servlet.utility.UmlExtractor;
|
||||
import net.sourceforge.plantuml.servlet.utility.UrlDataExtractor;
|
||||
|
||||
/**
|
||||
* Common service servlet to produce diagram from compressed UML source contained in the end part of the requested URI.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
@SuppressWarnings("SERIAL")
|
||||
public abstract class UmlDiagramService extends HttpServlet {
|
||||
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
|
||||
final String url = request.getRequestURI();
|
||||
final String encoded = UrlDataExtractor.getEncodedDiagram(url, "");
|
||||
final int idx = UrlDataExtractor.getIndex(url, 0);
|
||||
|
||||
// build the UML source from the compressed request parameter
|
||||
final String[] sourceAndIdx = getSourceAndIdx(request);
|
||||
final String uml;
|
||||
try {
|
||||
uml = UmlExtractor.getUmlSource(sourceAndIdx[0]);
|
||||
uml = UmlExtractor.getUmlSource(encoded);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Bad Request");
|
||||
return;
|
||||
}
|
||||
|
||||
doDiagramResponse(request, response, uml, idx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||
final int idx = UrlDataExtractor.getIndex(request.getRequestURI(), 0);
|
||||
|
||||
// read textual diagram source from request body
|
||||
final StringBuilder uml = new StringBuilder();
|
||||
try (BufferedReader in = request.getReader()) {
|
||||
String line;
|
||||
while ((line = in.readLine()) != null) {
|
||||
uml.append(line).append('\n');
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
// generate the response
|
||||
DiagramResponse dr = new DiagramResponse(response, getOutputFormat(), request);
|
||||
final int idx = Integer.parseInt(sourceAndIdx[1]);
|
||||
try {
|
||||
dr.sendDiagram(uml, idx);
|
||||
} catch (IIOException iioe) {
|
||||
} catch (IIOException e) {
|
||||
// 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 compressed UML source from the HTTP URI.
|
||||
*
|
||||
* @param uri
|
||||
* the complete URI as returned by request.getRequestURI()
|
||||
* @return the compressed UML source
|
||||
*/
|
||||
public final String[] getSourceAndIdx(HttpServletRequest request) {
|
||||
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(2);
|
||||
if (data.length() >= 4) {
|
||||
String idx = recoverUml.group(1);
|
||||
if (idx == null) {
|
||||
idx = "0";
|
||||
} else {
|
||||
idx = idx.substring(0, idx.length() - 1);
|
||||
}
|
||||
return new String[]{data, idx };
|
||||
}
|
||||
}
|
||||
return new String[]{"", "0" };
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -6,26 +6,33 @@ hide empty members
|
|||
hide empty methods
|
||||
hide empty fields
|
||||
abstract class UmlDiagramService {
|
||||
public void doGet(HttpServletRequest rq, HttpServletResponse rsp)
|
||||
abstract public String getSource( String uri)
|
||||
abstract FileFormat getOutputFormat()
|
||||
+ doGet(request: HttpServletRequest, response: HttpServletResponse) : void
|
||||
+ doPost(request: HttpServletRequest, response: HttpServletResponse) : void
|
||||
+ {abstract} getOutputFormat() : FileFormat
|
||||
}
|
||||
class DiagramResponse {
|
||||
DiagramResponse( HttpServletResponse r, FileFormat f)
|
||||
void sendDiagram( String uml)
|
||||
void sendMap( String uml)
|
||||
+ DiagramResponse(res: HttpServletResponse, fmt: FileFormat, req: HttpServletRequest)
|
||||
+ sendDiagram(uml: String, idx: int) : void
|
||||
+ sendMap(uml: String, idx: int) : void
|
||||
+ sendCheck(uml: String) : void
|
||||
}
|
||||
abstract HttpServlet <|-- UmlDiagramService
|
||||
abstract HttpServlet <|-- MapServlet
|
||||
abstract HttpServlet <|-- ProxyServlet
|
||||
UmlDiagramService <|-- PngServlet
|
||||
UmlDiagramService <|-- SvgServlet
|
||||
HttpServlet <|-- CheckSyntaxServlet
|
||||
HttpServlet <|-- LanguageServlet
|
||||
HttpServlet <|-- MapServlet
|
||||
HttpServlet <|-- PlantUmlServlet
|
||||
HttpServlet <|-- ProxyServlet
|
||||
HttpServlet <|-- OldProxyServlet
|
||||
HttpServlet <|-- UmlDiagramService
|
||||
UmlDiagramService <|-- AsciiServlet
|
||||
UmlDiagramService <|-- Base64Servlet
|
||||
UmlDiagramService <|-- EpsServlet
|
||||
UmlDiagramService <|-- EpsTextServlet
|
||||
UmlDiagramService <|-- AsciiServlet
|
||||
UmlDiagramService o- DiagramResponse
|
||||
MapServlet o-- DiagramResponse
|
||||
ProxyServlet o-- DiagramResponse
|
||||
UmlDiagramService <|-- ImgServlet
|
||||
UmlDiagramService <|-- SvgServlet
|
||||
UmlDiagramService o-- DiagramResponse
|
||||
DiagramResponse --o CheckSyntaxServlet
|
||||
DiagramResponse --o MapServlet
|
||||
DiagramResponse --o ProxyServlet
|
||||
@enduml
|
||||
|
||||
## Sequence diagram ##
|
||||
|
@ -33,14 +40,17 @@ ProxyServlet o-- DiagramResponse
|
|||
|
||||
@startuml
|
||||
title Generation of a PNG image illustrated
|
||||
PngServlet -> PngServlet : getSource()
|
||||
PngServlet -> UmlExtractor : getUmlSource()
|
||||
UmlExtractor --> PngServlet
|
||||
PngServlet -> PngServlet : getOutputFormat()
|
||||
PngServlet -> DiagramResponse : <<create>>
|
||||
PngServlet -> DiagramResponse : sendDiagram()
|
||||
ImgServlet -> UrlDataExtractor : getEncodedDiagram()
|
||||
UrlDataExtractor --> ImgServlet : encoded
|
||||
ImgServlet -> UrlDataExtractor : getIndex()
|
||||
UrlDataExtractor --> ImgServlet : index
|
||||
ImgServlet -> UmlExtractor : getUmlSource()
|
||||
UmlExtractor --> ImgServlet : decoded
|
||||
ImgServlet -> ImgServlet : getOutputFormat()
|
||||
ImgServlet -> "dr:DiagramResponse" as dr ** : <<create>>
|
||||
ImgServlet -> dr : sendDiagram()
|
||||
participant "PlantUML library" as Lib #99FF99
|
||||
DiagramResponse -> Lib : generateImage()
|
||||
Lib --> DiagramResponse
|
||||
DiagramResponse --> PngServlet
|
||||
@enduml
|
||||
dr -> Lib : generateImage()
|
||||
Lib --> dr
|
||||
dr --> ImgServlet
|
||||
@enduml
|
||||
|
|
|
@ -1,15 +1,21 @@
|
|||
<html>
|
||||
<body>
|
||||
<p>This package is in charge of the JEE PlantUml Server.</p>
|
||||
<p>there are 2 kind of servlets in this package :<br>
|
||||
- Interactive servlets : Welcome, PlantUmlServlet that are in charge of the web pages dedicated to human users.<br>
|
||||
- Service servlets : ImgServlet, SvgServlet, EpsServlet, EpsTextServlet, AsciiServlet, ProxyServlet that only produce a diagram as output.<br>
|
||||
<br>
|
||||
Structure of the service part of the PlantUmlServer: <br>
|
||||
<img src="http://www.plantuml.com/plantuml/img/XP51ReCm44Ntd6AMH0etwAPIbNPJjIhg0OoPm4WsTiPZrAZDtGk5913IP3b_dlx_7jTK8g3riWUBja0EIJsLf7RbJDeIcavHHH1MMa0R5G9yMlD4gc9bS-IMDC9t0k1ZOKX3wwY4qZsZf2yYlYSCoWVk8WO1tgrX9WVlce30mQywZrFGQ9OBKrD1XPAxo1hJenAPPlo636uSMoKz_1R5HndcT9KSag7tMFeKshU-qDBhxTRJW6sV_FVCW4qv6foRMJFRloe_tntEvvnamSDFbYqlUuFjZCVv1lJExcj_n9R_DZ1DTOV8stl4Oz14_pCkkpnqSgxVRPVhQV5hm2y0" />
|
||||
</p>
|
||||
<p>
|
||||
<img src="http://www.plantuml.com/plantuml/img/XP1DZi8m38NtdCA23RFe0OfGLr24n4y5uW2cU2fBQL8vBeBRup8ZHEc2LPJtNhuNMraTmOey2Ie73-4N48hT2hZ6Ye2TQwEQHvTHuQiZoTMHGfB1ssq65Uanj5BIzESZTghTycQ0KeFy1KrvPNjkqgD-gTktshIQ1wbH1wKBnagmFb1iWezaB-RpKiYcoBAlqKZ-ygyQk45HBhb1hp0kd1sdxGOSdmNbFWQCiE4pJD8qpzDqz4cpWixkVlpSCAsxhHgsKvDX_H3G6_q1" />
|
||||
</p>
|
||||
<p>This package is in charge of the JEE PlantUml Server.</p>
|
||||
<p>There are 2 kind of servlets in this package:<br>
|
||||
- Interactive servlets: Welcome, PlantUmlServlet that are in charge of the web pages dedicated to human users.<br>
|
||||
- Service servlets: ImgServlet, SvgServlet, EpsServlet, EpsTextServlet, AsciiServlet, ProxyServlet that only produce a diagram as output.<br>
|
||||
<br>
|
||||
Structure of the service part of the PlantUmlServer: <br>
|
||||
<img
|
||||
alt="Class diagram of the service part of the PlantUmlServer"
|
||||
src="https://www.plantuml.com/plantuml/svg/XP31Ri8m44Jl_eez1Wd-e0SgLRGNrAfHFy3OIx1ansQzHaKj_zv4mKfCYZXwvcbclEl8aZWvAmv68w0BV0Q7ReSKIuaFNXVItg3j5BcBJ58nl3676kbaaKTHMHaZV3dxOcH3qlM0KGW_0Y2adJKAJjveqFuLkPf4VE8nOMIWun8AEGRVHWIAOI40Sb4EgvbCsq23NFj42gki9385lp4MDvwSv1v-JnmI3-zg8IvYs7qTdKlxrRTQzV-wvRHWtpKFtupOwcl0kCpPmj_AK7eNCQc0fz_L2hOol-VU1_dlStRdbn-Ojdb0rAT7n7DKnjnd_EhsL69StRbpEm-_2wonrSdPFm00"
|
||||
>
|
||||
</p>
|
||||
<p>
|
||||
<img
|
||||
alt="Generation of a PNG image illustrated"
|
||||
src="https://www.plantuml.com/plantuml/svg/XP1DZi8m38NtdCA23RFe0OfGLr24n4y5uW2cU2fBQL8vBeBRup8ZHEc2LPJtNhuNMraTmOey2Ie73-4N48hT2hZ6Ye2TQwEQHvTHuQiZoTMHGfB1ssq65Uanj5BIzESZTghTycQ0KeFy1KrvPNjkqgD-gTktshIQ1wbH1wKBnagmFb1iWezaB-RpKiYcoBAlqKZ-ygyQk45HBhb1hp0kd1sdxGOSdmNbFWQCiE4pJD8qpzDqz4cpWixkVlpSCAsxhHgsKvDX_H3G6_q1"
|
||||
>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
* Project Info: https://plantuml.com
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
|
@ -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,15 +78,17 @@ 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"
|
||||
*/
|
||||
public static boolean get(final String key) {
|
||||
if (instance.config.getProperty(key) == null) {
|
||||
if (get().getProperty(key) == null) {
|
||||
return false;
|
||||
}
|
||||
return instance.config.getProperty(key).startsWith("on");
|
||||
return get().getProperty(key).startsWith("on");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
* Project Info: https://plantuml.com
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
* Project Info: https://plantuml.com
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
|
@ -27,24 +27,29 @@ import java.io.IOException;
|
|||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
|
||||
import net.sourceforge.plantuml.FileFormat;
|
||||
import net.sourceforge.plantuml.FileFormatOption;
|
||||
import net.sourceforge.plantuml.SourceStringReader;
|
||||
import net.sourceforge.plantuml.code.Transcoder;
|
||||
import net.sourceforge.plantuml.code.TranscoderUtil;
|
||||
import net.sourceforge.plantuml.core.Diagram;
|
||||
import net.sourceforge.plantuml.core.ImageData;
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
|
||||
/**
|
||||
* Build the complete UML source from the compressed source extracted from the HTTP URI.
|
||||
* Build the complete UML source from the compressed source extracted from the
|
||||
* HTTP URI.
|
||||
*
|
||||
* @param source the last part of the URI containing the compressed UML
|
||||
*
|
||||
* @param source
|
||||
* the last part of the URI containing the compressed UML
|
||||
* @return the textual UML source
|
||||
*/
|
||||
static public String getUmlSource(String source) {
|
||||
|
||||
// build the UML source from the compressed part of the URL
|
||||
String text;
|
||||
try {
|
||||
|
@ -76,9 +81,36 @@ public class UmlExtractor {
|
|||
return uml;
|
||||
}
|
||||
|
||||
protected UmlExtractor() {
|
||||
// prevents calls from subclass
|
||||
throw new UnsupportedOperationException();
|
||||
/**
|
||||
* Get image map from uml.
|
||||
*
|
||||
* @param uml textual diagram source
|
||||
*
|
||||
* @return image map of the diagram in HTML format if the image has some position information; otherwise `null`
|
||||
*
|
||||
* @throws IOException if an input or output exception occurred
|
||||
*/
|
||||
public static String extractMap(final String uml) throws IOException {
|
||||
return extractMap(uml, FileFormat.PNG);
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* Get image map from uml.
|
||||
*
|
||||
* @param uml textual diagram source
|
||||
* @param fileFormat underlying file format of uml image
|
||||
*
|
||||
* @return image map of the diagram in HTML format if the image has some position information; otherwise `null`
|
||||
*
|
||||
* @throws IOException if an input or output exception occurred
|
||||
*/
|
||||
public static String extractMap(final String uml, final FileFormat fileFormat) throws IOException {
|
||||
Diagram diagram = new SourceStringReader(uml).getBlocks().get(0).getDiagram();
|
||||
ImageData map = diagram.exportDiagram(new NullOutputStream(), 0, new FileFormatOption(fileFormat, false));
|
||||
if (map.containsCMapData()) {
|
||||
return map.getCMapData("plantuml");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: https://plantuml.com
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.servlet.utility;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Utility class to extract the index and diagram source from an URL, e.g., returned by `request.getRequestURI()`.
|
||||
*/
|
||||
public abstract class UrlDataExtractor {
|
||||
|
||||
/**
|
||||
* URL regex pattern to easily extract index and encoded diagram.
|
||||
*/
|
||||
private static final Pattern URL_PATTERN = Pattern.compile(
|
||||
"/\\w+(?:/(?<idx>\\d+))?(?:/(?<encoded>[^/]+))?/?$"
|
||||
);
|
||||
|
||||
/**
|
||||
* Get diagram index from URL.
|
||||
*
|
||||
* @param url URL to analyse, e.g., returned by `request.getRequestURI()`
|
||||
*
|
||||
* @return if exists diagram index; otherwise -1
|
||||
*/
|
||||
public static int getIndex(final String url) {
|
||||
return getIndex(url, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get diagram index from URL.
|
||||
*
|
||||
* @param url URL to analyse, e.g., returned by `request.getRequestURI()`
|
||||
* @param fallback fallback index if no index exists in {@code url}
|
||||
*
|
||||
* @return if exists diagram index; otherwise {@code fallback}
|
||||
*/
|
||||
public static int getIndex(final String url, final int fallback) {
|
||||
final Matcher matcher = URL_PATTERN.matcher(url);
|
||||
if (!matcher.find()) {
|
||||
return fallback;
|
||||
}
|
||||
String idx = matcher.group("idx");
|
||||
if (idx == null) {
|
||||
return fallback;
|
||||
}
|
||||
return Integer.parseInt(idx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get encoded diagram source from URL.
|
||||
*
|
||||
* @param url URL to analyse, e.g., returned by `request.getRequestURI()`
|
||||
*
|
||||
* @return if exists diagram index; otherwise `null`
|
||||
*/
|
||||
public static String getEncodedDiagram(final String url) {
|
||||
return getEncodedDiagram(url, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get encoded diagram source from URL.
|
||||
*
|
||||
* @param url URL to analyse, e.g., returned by `request.getRequestURI()`
|
||||
* @param fallback fallback if no encoded diagram source exists in {@code url}
|
||||
*
|
||||
* @return if exists diagram index; otherwise {@code fallback}
|
||||
*/
|
||||
public static String getEncodedDiagram(final String url, final String fallback) {
|
||||
final Matcher matcher = URL_PATTERN.matcher(url);
|
||||
if (!matcher.find()) {
|
||||
return fallback;
|
||||
}
|
||||
String encoded = matcher.group("encoded");
|
||||
if (encoded == null) {
|
||||
return fallback;
|
||||
}
|
||||
return encoded;
|
||||
}
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
<html>
|
||||
<body>
|
||||
<p>This package contains utility classes of the JEE PlantUml Server.</p>
|
||||
<ul>
|
||||
<li>NullOutputStream is used by the Map feature.</li>
|
||||
<li>UmlExtractor encapsulates the PlantUML library to decode the UML compressed source.</li>
|
||||
</ul>
|
||||
<p>This package contains utility classes of the JEE PlantUml Server.</p>
|
||||
<ul>
|
||||
<li>NullOutputStream is used by the Map feature.</li>
|
||||
<li>UmlExtractor encapsulates the PlantUML library to decode the UML compressed source.</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
6
src/main/resources/log4j.properties
Normal file
|
@ -0,0 +1,6 @@
|
|||
# Logger configuration file
|
||||
#
|
||||
log4j.rootCategory=INFO, stdout
|
||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern=%d{yy-MM-dd HH:mm:ss:SSS} %5p %t %c{2}:%L - %m%n
|
|
@ -1,122 +1,255 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
|
||||
<display-name>plantuml</display-name>
|
||||
<context-param>
|
||||
<param-name>org.eclipse.jetty.servlet.Default.welcomeServlets</param-name>
|
||||
<param-value>exact</param-value>
|
||||
</context-param>
|
||||
<servlet>
|
||||
<servlet-name>plantumlservlet</servlet-name>
|
||||
<servlet-class>net.sourceforge.plantuml.servlet.PlantUmlServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet>
|
||||
<servlet-name>welcome</servlet-name>
|
||||
<servlet-class>net.sourceforge.plantuml.servlet.Welcome</servlet-class>
|
||||
</servlet>
|
||||
<servlet>
|
||||
<servlet-name>imgservlet</servlet-name>
|
||||
<servlet-class>net.sourceforge.plantuml.servlet.ImgServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet>
|
||||
<servlet-name>svgservlet</servlet-name>
|
||||
<servlet-class>net.sourceforge.plantuml.servlet.SvgServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet>
|
||||
<servlet-name>epsservlet</servlet-name>
|
||||
<servlet-class>net.sourceforge.plantuml.servlet.EpsServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet>
|
||||
<servlet-name>epstextservlet</servlet-name>
|
||||
<servlet-class>net.sourceforge.plantuml.servlet.EpsTextServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet>
|
||||
<servlet-name>asciiservlet</servlet-name>
|
||||
<servlet-class>net.sourceforge.plantuml.servlet.AsciiServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet>
|
||||
<servlet-name>proxyservlet</servlet-name>
|
||||
<servlet-class>net.sourceforge.plantuml.servlet.ProxyServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet>
|
||||
<servlet-name>oldproxyservlet</servlet-name>
|
||||
<servlet-class>net.sourceforge.plantuml.servlet.OldProxyServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet>
|
||||
<servlet-name>mapservlet</servlet-name>
|
||||
<servlet-class>net.sourceforge.plantuml.servlet.MapServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet>
|
||||
<servlet-name>checkservlet</servlet-name>
|
||||
<servlet-class>net.sourceforge.plantuml.servlet.CheckSyntaxServlet</servlet-class>
|
||||
</servlet>
|
||||
<!-- Patterns of the servlet -->
|
||||
<servlet-mapping>
|
||||
<servlet-name>plantumlservlet</servlet-name>
|
||||
<url-pattern>/welcome</url-pattern>
|
||||
</servlet-mapping>
|
||||
<servlet-mapping>
|
||||
<servlet-name>plantumlservlet</servlet-name>
|
||||
<url-pattern>/uml/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
<servlet-mapping>
|
||||
<servlet-name>plantumlservlet</servlet-name>
|
||||
<url-pattern>/form</url-pattern>
|
||||
</servlet-mapping>
|
||||
<servlet-mapping>
|
||||
<servlet-name>imgservlet</servlet-name>
|
||||
<url-pattern>/png/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
<servlet-mapping>
|
||||
<servlet-name>imgservlet</servlet-name>
|
||||
<url-pattern>/img/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
<servlet-mapping>
|
||||
<servlet-name>svgservlet</servlet-name>
|
||||
<url-pattern>/svg/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
<servlet-mapping>
|
||||
<servlet-name>epsservlet</servlet-name>
|
||||
<url-pattern>/eps/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
<servlet-mapping>
|
||||
<servlet-name>epstextservlet</servlet-name>
|
||||
<url-pattern>/epstext/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
<servlet-mapping>
|
||||
<servlet-name>asciiservlet</servlet-name>
|
||||
<url-pattern>/txt/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
<servlet-mapping>
|
||||
<servlet-name>checkservlet</servlet-name>
|
||||
<url-pattern>/check/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
<servlet-mapping>
|
||||
<servlet-name>mapservlet</servlet-name>
|
||||
<url-pattern>/map/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
<servlet-mapping>
|
||||
<servlet-name>plantumlservlet</servlet-name>
|
||||
<url-pattern>/start/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
<servlet-mapping>
|
||||
<servlet-name>oldproxyservlet</servlet-name>
|
||||
<url-pattern>/proxy/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
<servlet-mapping>
|
||||
<servlet-name>proxyservlet</servlet-name>
|
||||
<url-pattern>/proxy</url-pattern>
|
||||
</servlet-mapping>
|
||||
<error-page>
|
||||
<exception-type>java.lang.Throwable</exception-type>
|
||||
<location>/error.jsp</location>
|
||||
</error-page>
|
||||
<error-page>
|
||||
<error-code>500</error-code>
|
||||
<location>/error.jsp</location>
|
||||
</error-page>
|
||||
<welcome-file-list>
|
||||
<welcome-file>welcome</welcome-file>
|
||||
</welcome-file-list>
|
||||
</web-app>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app
|
||||
xmlns="https://jakarta.ee/xml/ns/jakartaee"
|
||||
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:web="https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
|
||||
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
|
||||
version="5.0"
|
||||
>
|
||||
|
||||
<!-- ========================================================== -->
|
||||
<!-- General -->
|
||||
<!-- ========================================================== -->
|
||||
|
||||
<!-- Name the application -->
|
||||
<display-name>PlantUML</display-name>
|
||||
<description>PlantUML Online Server</description>
|
||||
|
||||
<!-- This app is cluster-ready -->
|
||||
<distributable />
|
||||
|
||||
<!-- Set timeout to 120 minutes -->
|
||||
<session-config>
|
||||
<session-timeout>120</session-timeout>
|
||||
</session-config>
|
||||
|
||||
|
||||
<!-- ========================================================== -->
|
||||
<!-- Custom Tag Libraries -->
|
||||
<!-- ========================================================== -->
|
||||
|
||||
<!-- Taglib declarations are no longer required since JSP 2.0, see Removing taglib from web.xml -->
|
||||
<!-- The <taglib> did not need to be a child of <jsp-config> in earlier versions but is required as of Tomcat 7 -->
|
||||
<!-- Note that you can only have one <jsp-config> element per web.xml -->
|
||||
<!--
|
||||
<jsp-config>
|
||||
<taglib>
|
||||
<taglib-uri>http://java.sun.com/jsp/jstl/core</taglib-uri>
|
||||
<taglib-location>/WEB-INF/lib/c.tld</taglib-location>
|
||||
</taglib>
|
||||
</jsp-config>
|
||||
-->
|
||||
|
||||
|
||||
<!-- ========================================================== -->
|
||||
<!-- Context Parameters -->
|
||||
<!-- ========================================================== -->
|
||||
|
||||
<context-param>
|
||||
<param-name>org.eclipse.jetty.servlet.Default.welcomeServlets</param-name>
|
||||
<param-value>exact</param-value>
|
||||
</context-param>
|
||||
|
||||
|
||||
<!-- ========================================================== -->
|
||||
<!-- Servlets -->
|
||||
<!-- ========================================================== -->
|
||||
|
||||
<servlet>
|
||||
<servlet-name>jsp</servlet-name>
|
||||
<servlet-class>org.eclipse.jetty.jsp.JettyJspServlet</servlet-class>
|
||||
<init-param>
|
||||
<param-name>compilerSourceVM</param-name>
|
||||
<param-value>1.8</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<param-name>compilerTargetVM</param-name>
|
||||
<param-value>1.8</param-value>
|
||||
</init-param>
|
||||
</servlet>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>plantumlservlet</servlet-name>
|
||||
<servlet-class>net.sourceforge.plantuml.servlet.PlantUmlServlet</servlet-class>
|
||||
<load-on-startup>0</load-on-startup>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>plantumlservlet</servlet-name>
|
||||
<url-pattern>/welcome</url-pattern>
|
||||
</servlet-mapping>
|
||||
<servlet-mapping>
|
||||
<servlet-name>plantumlservlet</servlet-name>
|
||||
<url-pattern>/uml/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
<servlet-mapping>
|
||||
<servlet-name>plantumlservlet</servlet-name>
|
||||
<url-pattern>/form</url-pattern>
|
||||
</servlet-mapping>
|
||||
<servlet-mapping>
|
||||
<servlet-name>plantumlservlet</servlet-name>
|
||||
<url-pattern>/start/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>imgservlet</servlet-name>
|
||||
<servlet-class>net.sourceforge.plantuml.servlet.ImgServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>imgservlet</servlet-name>
|
||||
<url-pattern>/png/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
<servlet-mapping>
|
||||
<servlet-name>imgservlet</servlet-name>
|
||||
<url-pattern>/img/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>svgservlet</servlet-name>
|
||||
<servlet-class>net.sourceforge.plantuml.servlet.SvgServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>svgservlet</servlet-name>
|
||||
<url-pattern>/svg/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>pdfservlet</servlet-name>
|
||||
<servlet-class>net.sourceforge.plantuml.servlet.PdfServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>pdfservlet</servlet-name>
|
||||
<url-pattern>/pdf/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>epsservlet</servlet-name>
|
||||
<servlet-class>net.sourceforge.plantuml.servlet.EpsServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>epsservlet</servlet-name>
|
||||
<url-pattern>/eps/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>epstextservlet</servlet-name>
|
||||
<servlet-class>net.sourceforge.plantuml.servlet.EpsTextServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>epstextservlet</servlet-name>
|
||||
<url-pattern>/epstext/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>base64servlet</servlet-name>
|
||||
<servlet-class>net.sourceforge.plantuml.servlet.Base64Servlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>base64servlet</servlet-name>
|
||||
<url-pattern>/base64/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>asciiservlet</servlet-name>
|
||||
<servlet-class>net.sourceforge.plantuml.servlet.AsciiServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>asciiservlet</servlet-name>
|
||||
<url-pattern>/txt/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>proxyservlet</servlet-name>
|
||||
<servlet-class>net.sourceforge.plantuml.servlet.ProxyServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>proxyservlet</servlet-name>
|
||||
<url-pattern>/proxy</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>oldproxyservlet</servlet-name>
|
||||
<servlet-class>net.sourceforge.plantuml.servlet.OldProxyServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>oldproxyservlet</servlet-name>
|
||||
<url-pattern>/proxy/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>mapservlet</servlet-name>
|
||||
<servlet-class>net.sourceforge.plantuml.servlet.MapServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>mapservlet</servlet-name>
|
||||
<url-pattern>/map/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>checkservlet</servlet-name>
|
||||
<servlet-class>net.sourceforge.plantuml.servlet.CheckSyntaxServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>checkservlet</servlet-name>
|
||||
<url-pattern>/check/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>languageservlet</servlet-name>
|
||||
<servlet-class>net.sourceforge.plantuml.servlet.LanguageServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>languageservlet</servlet-name>
|
||||
<url-pattern>/language</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>asciicoderservlet</servlet-name>
|
||||
<servlet-class>net.sourceforge.plantuml.servlet.AsciiCoderServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>asciicoderservlet</servlet-name>
|
||||
<url-pattern>/coder/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>plantumluihelperservlet</servlet-name>
|
||||
<servlet-class>net.sourceforge.plantuml.servlet.PlantUmlUIHelperServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>plantumluihelperservlet</servlet-name>
|
||||
<url-pattern>/ui-helper/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>metadataservlet</servlet-name>
|
||||
<servlet-class>net.sourceforge.plantuml.servlet.MetadataServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>metadataservlet</servlet-name>
|
||||
<url-pattern>/metadata/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<!-- ========================================================== -->
|
||||
<!-- Error Handler -->
|
||||
<!-- ========================================================== -->
|
||||
|
||||
<error-page>
|
||||
<exception-type>java.lang.Throwable</exception-type>
|
||||
<location>/error.jsp</location>
|
||||
</error-page>
|
||||
|
||||
<error-page>
|
||||
<error-code>500</error-code>
|
||||
<location>/error.jsp</location>
|
||||
</error-page>
|
||||
|
||||
|
||||
<!-- ========================================================== -->
|
||||
<!-- Welcome Files -->
|
||||
<!-- ========================================================== -->
|
||||
|
||||
<welcome-file-list>
|
||||
<welcome-file>welcome</welcome-file>
|
||||
</welcome-file-list>
|
||||
|
||||
</web-app>
|
||||
|
|
1
src/main/webapp/assets/actions/copy.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg height="24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M16 16v4c0 1.152-.848 2-2 2H4c-1.152 0-2-.848-2-2V10c0-1.152.848-2 2-2h4V4c0-1.152.848-2 2-2h10c1.152 0 2 .848 2 2v10c0 1.152-.848 2-2 2h-4zm-2 0h-4c-1.152 0-2-.848-2-2v-4H4v10h10v-4zM10 4v10h10V4H10z" fill-rule="evenodd"/></svg>
|
After Width: | Height: | Size: 301 B |
1
src/main/webapp/assets/actions/dock.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg height="512" width="512" xmlns="http://www.w3.org/2000/svg"><path d="M384 224v184a40 40 0 01-40 40H104a40 40 0 01-40-40V168a40 40 0 0140-40h167.48" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/><path fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="M216 184v112h112m-104-8L440 72"/></svg>
|
After Width: | Height: | Size: 384 B |
1
src/main/webapp/assets/actions/download.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M7 10l5 5 5-5M12 15V3"/></svg>
|
After Width: | Height: | Size: 240 B |
1
src/main/webapp/assets/actions/settings.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg height="512" width="512" xmlns="http://www.w3.org/2000/svg"><path d="M262.29 192.31a64 64 0 1057.4 57.4 64.13 64.13 0 00-57.4-57.4zM416.39 256a154.34 154.34 0 01-1.53 20.79l45.21 35.46a10.81 10.81 0 012.45 13.75l-42.77 74a10.81 10.81 0 01-13.14 4.59l-44.9-18.08a16.11 16.11 0 00-15.17 1.75A164.48 164.48 0 01325 400.8a15.94 15.94 0 00-8.82 12.14l-6.73 47.89a11.08 11.08 0 01-10.68 9.17h-85.54a11.11 11.11 0 01-10.69-8.87l-6.72-47.82a16.07 16.07 0 00-9-12.22 155.3 155.3 0 01-21.46-12.57 16 16 0 00-15.11-1.71l-44.89 18.07a10.81 10.81 0 01-13.14-4.58l-42.77-74a10.8 10.8 0 012.45-13.75l38.21-30a16.05 16.05 0 006-14.08c-.36-4.17-.58-8.33-.58-12.5s.21-8.27.58-12.35a16 16 0 00-6.07-13.94l-38.19-30A10.81 10.81 0 0149.48 186l42.77-74a10.81 10.81 0 0113.14-4.59l44.9 18.08a16.11 16.11 0 0015.17-1.75A164.48 164.48 0 01187 111.2a15.94 15.94 0 008.82-12.14l6.73-47.89A11.08 11.08 0 01213.23 42h85.54a11.11 11.11 0 0110.69 8.87l6.72 47.82a16.07 16.07 0 009 12.22 155.3 155.3 0 0121.46 12.57 16 16 0 0015.11 1.71l44.89-18.07a10.81 10.81 0 0113.14 4.58l42.77 74a10.8 10.8 0 01-2.45 13.75l-38.21 30a16.05 16.05 0 00-6.05 14.08c.33 4.14.55 8.3.55 12.47z" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/></svg>
|
After Width: | Height: | Size: 1.2 KiB |
1
src/main/webapp/assets/actions/undock.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg height="512" width="512" xmlns="http://www.w3.org/2000/svg"><path d="M384 224v184a40 40 0 01-40 40H104a40 40 0 01-40-40V168a40 40 0 0140-40h167.48M336 64h112v112M224 288L440 72" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/></svg>
|
After Width: | Height: | Size: 281 B |
1
src/main/webapp/assets/actions/upload.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M17 8l-5-5-5 5M12 3v12"/></svg>
|
After Width: | Height: | Size: 241 B |
1
src/main/webapp/assets/file-types/ascii.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg class="bi bi-filetype-ascii" fill="currentColor" height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M14 4.5V11h-1V4.5h-2A1.5 1.5 0 019.5 3V1H4a1 1 0 00-1 1v9H2V2a2 2 0 012-2h5.5zM2.404 14.903l-.313 1.028h-.8l1.342-3.999h.926l1.335 4h-.84l-.314-1.03H2.404zm1.178-.59l-.49-1.616h-.034l-.49 1.617h1.014zm1.782.977a1.178 1.178 0 01-.111-.449h.764a.58.58 0 00.255.384c.07.049.154.087.25.114.095.028.2.041.319.041.164 0 .3-.023.413-.07a.558.558 0 00.255-.193.507.507 0 00.085-.29.387.387 0 00-.153-.326c-.101-.08-.256-.144-.463-.193l-.618-.143a1.72 1.72 0 01-.54-.214 1.002 1.002 0 01-.35-.367 1.068 1.068 0 01-.123-.524c0-.244.063-.457.19-.639.127-.181.303-.322.527-.422.225-.1.484-.149.777-.149.304 0 .564.05.779.152.217.102.384.239.5.41.12.17.186.359.2.566h-.75a.56.56 0 00-.12-.258.623.623 0 00-.246-.181.923.923 0 00-.37-.068c-.216 0-.387.05-.512.152a.472.472 0 00-.184.384c0 .121.047.22.143.3a.97.97 0 00.404.175l.62.143c.218.05.407.12.567.211.16.09.285.21.375.358.09.148.135.335.135.56 0 .247-.063.466-.188.656-.133.196-.32.348-.54.439-.233.105-.52.158-.857.158a2.191 2.191 0 01-.665-.09 1.404 1.404 0 01-.478-.252 1.131 1.131 0 01-.29-.375zm4.383-2.246a1.732 1.732 0 00-.103.633v.495c0 .246.035.455.103.627a.834.834 0 00.299.393c.142.09.308.136.477.13a.872.872 0 00.402-.087.699.699 0 00.272-.248.8.8 0 00.117-.364h.765v.076c-.01.241-.088.475-.226.674-.136.194-.32.345-.55.454a1.81 1.81 0 01-.785.164c-.36 0-.665-.072-.915-.216a1.424 1.424 0 01-.57-.627c-.13-.272-.194-.597-.194-.976v-.498c0-.38.065-.705.196-.978.13-.274.32-.485.57-.633.253-.15.557-.223.913-.223.218 0 .42.032.606.097.187.062.35.153.49.272.283.241.452.591.465.964v.073h-.765a.85.85 0 00-.12-.38.7.7 0 00-.272-.261.802.802 0 00-.4-.097.814.814 0 00-.473.138.868.868 0 00-.302.398zm3.628-1.106v4h-.79v-4h.79zm1.337.005v3.999h-.791v-4h.79z" fill-rule="evenodd"/></svg>
|
After Width: | Height: | Size: 1.8 KiB |
1
src/main/webapp/assets/file-types/map.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg class="bi bi-filetype-map" fill="currentColor" height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M14 4.5V14a2 2 0 01-2 2v-1a1 1 0 001-1V4.5h-2A1.5 1.5 0 019.5 3V1H4a1 1 0 00-1 1v9H2V2a2 2 0 012-2h5.5zM.706 15.849v-2.66h.038l.952 2.16h.516l.946-2.16h.038v2.66h.715V11.85h-.8l-1.14 2.596h-.026L.805 11.85H0v3.999zm7.31-3.999h1.6c.289 0 .533.06.732.179.201.117.355.276.46.477.106.201.158.427.158.677 0 .25-.053.476-.16.677-.106.199-.26.357-.464.474a1.46 1.46 0 01-.732.173h-.803v1.342h-.79V11.85zm2.06 1.714a.795.795 0 00.085-.381c0-.226-.062-.4-.185-.521-.123-.122-.294-.182-.513-.182h-.659v1.406h.66a.794.794 0 00.374-.082.574.574 0 00.238-.24zm-5.12 2.306l.313-1.028h1.336l.314 1.028h.84l-1.336-3.999h-.925l-1.329 3.96m1.79-3.195l.488 1.617H5.433l.49-1.617z" fill-rule="evenodd"/></svg>
|
After Width: | Height: | Size: 808 B |
1
src/main/webapp/assets/file-types/pdf.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg class="bi bi-filetype-pdf" fill="currentColor" height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M14 4.5V14a2 2 0 01-2 2h-1v-1h1a1 1 0 001-1V4.5h-2A1.5 1.5 0 019.5 3V1H4a1 1 0 00-1 1v9H2V2a2 2 0 012-2h5.5L14 4.5zM1.6 11.85H0v3.999h.791v-1.342h.803c.287 0 .531-.057.732-.173.203-.117.358-.275.463-.474a1.42 1.42 0 00.161-.677c0-.25-.053-.476-.158-.677a1.176 1.176 0 00-.46-.477c-.2-.12-.443-.179-.732-.179zm.545 1.333a.795.795 0 01-.085.38.574.574 0 01-.238.241.794.794 0 01-.375.082H.788V12.48h.66c.218 0 .389.06.512.181.123.122.185.296.185.522zm1.217-1.333v3.999h1.46c.401 0 .734-.08.998-.237a1.45 1.45 0 00.595-.689c.13-.3.196-.662.196-1.084 0-.42-.065-.778-.196-1.075a1.426 1.426 0 00-.589-.68c-.264-.156-.599-.234-1.005-.234H3.362zm.791.645h.563c.248 0 .45.05.609.152a.89.89 0 01.354.454c.079.201.118.452.118.753a2.3 2.3 0 01-.068.592 1.14 1.14 0 01-.196.422.8.8 0 01-.334.252 1.298 1.298 0 01-.483.082h-.563v-2.707zm3.743 1.763v1.591h-.79V11.85h2.548v.653H7.896v1.117h1.606v.638H7.896z" fill-rule="evenodd"/></svg>
|
After Width: | Height: | Size: 1.0 KiB |
1
src/main/webapp/assets/file-types/png.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg class="bi bi-filetype-png" fill="currentColor" height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M14 4.5V14a2 2 0 01-2 2v-1a1 1 0 001-1V4.5h-2A1.5 1.5 0 019.5 3V1H4a1 1 0 00-1 1v9H2V2a2 2 0 012-2h5.5L14 4.5zm-3.76 8.132c.076.153.123.317.14.492h-.776a.797.797 0 00-.097-.249.689.689 0 00-.17-.19.707.707 0 00-.237-.126.96.96 0 00-.299-.044c-.285 0-.506.1-.665.302-.156.201-.234.484-.234.85v.498c0 .234.032.439.097.615a.881.881 0 00.304.413.87.87 0 00.519.146.967.967 0 00.457-.096.67.67 0 00.272-.264c.06-.11.091-.23.091-.363v-.255H8.82v-.59h1.576v.798c0 .193-.032.377-.097.55a1.29 1.29 0 01-.293.458 1.37 1.37 0 01-.495.313c-.197.074-.43.111-.697.111a1.98 1.98 0 01-.753-.132 1.447 1.447 0 01-.533-.377 1.58 1.58 0 01-.32-.58 2.482 2.482 0 01-.105-.745v-.506c0-.362.067-.678.2-.95.134-.271.328-.482.582-.633.256-.152.565-.228.926-.228.238 0 .45.033.636.1.187.066.348.158.48.275.133.117.238.253.314.407zm-8.64-.706H0v4h.791v-1.343h.803c.287 0 .531-.057.732-.172.203-.118.358-.276.463-.475a1.42 1.42 0 00.161-.677c0-.25-.053-.475-.158-.677a1.176 1.176 0 00-.46-.477c-.2-.12-.443-.179-.732-.179zm.545 1.333a.795.795 0 01-.085.381.574.574 0 01-.238.24.794.794 0 01-.375.082H.788v-1.406h.66c.218 0 .389.06.512.182.123.12.185.295.185.521zm1.964 2.666V13.25h.032l1.761 2.675h.656v-3.999h-.75v2.66h-.032l-1.752-2.66h-.662v4h.747z" fill-rule="evenodd"/></svg>
|
After Width: | Height: | Size: 1.3 KiB |