]>
git.argeo.org Git - lgpl/argeo-commons.git/blob - servlet/CmsRcpServletFactory.java
1 package org
.argeo
.cms
.ui
.rcp
.servlet
;
3 import static java
.lang
.System
.Logger
.Level
.DEBUG
;
5 import java
.io
.IOException
;
6 import java
.lang
.System
.Logger
;
7 import java
.lang
.System
.Logger
.Level
;
8 import java
.net
.DatagramSocket
;
9 import java
.net
.ServerSocket
;
11 import java
.nio
.charset
.StandardCharsets
;
12 import java
.nio
.file
.Files
;
13 import java
.nio
.file
.Path
;
15 import java
.util
.concurrent
.CompletableFuture
;
17 import org
.argeo
.api
.cms
.CmsApp
;
18 import org
.argeo
.cms
.ui
.rcp
.CmsRcpDisplayFactory
;
20 import com
.sun
.net
.httpserver
.HttpExchange
;
21 import com
.sun
.net
.httpserver
.HttpHandler
;
22 import com
.sun
.net
.httpserver
.HttpServer
;
24 /** Publishes one {@link CmsRcpServlet} per {@link CmsApp}. */
25 public class CmsRcpServletFactory
{
26 private final static Logger logger
= System
.getLogger(CmsRcpServletFactory
.class.getName());
27 private CompletableFuture
<HttpServer
> httpServer
=new CompletableFuture
<>();
33 public void destroy() {
34 Path runFile
= CmsRcpDisplayFactory
.getUrlRunFile();
36 if (Files
.exists(runFile
)) {
37 Files
.delete(runFile
);
39 } catch (IOException e
) {
40 logger
.log(Level
.ERROR
, "Cannot delete " + runFile
, e
);
44 public void addCmsApp(CmsApp cmsApp
, Map
<String
, String
> properties
) {
45 final String contextName
= properties
.get(CmsApp
.CONTEXT_NAME_PROPERTY
);
46 if (contextName
!= null) {
47 httpServer
.thenAcceptAsync((httpServer
) -> {
48 httpServer
.createContext("/" + contextName
, new HttpHandler() {
51 public void handle(HttpExchange exchange
) throws IOException
{
52 String path
= exchange
.getRequestURI().getPath();
53 String uiName
= path
!= null ? path
.substring(path
.lastIndexOf('/') + 1) : "";
54 CmsRcpDisplayFactory
.openCmsApp(cmsApp
, uiName
, null);
55 exchange
.sendResponseHeaders(200, -1);
56 logger
.log(Level
.DEBUG
, "Opened RCP UI " + uiName
+ " of CMS App /" + contextName
);
60 logger
.log(Level
.DEBUG
, "Registered RCP CMS APP /" + contextName
);
64 public void removeCmsApp(CmsApp cmsApp
, Map
<String
, String
> properties
) {
65 String contextName
= properties
.get(CmsApp
.CONTEXT_NAME_PROPERTY
);
66 if (contextName
!= null) {
67 httpServer
.thenAcceptAsync((httpServer
) -> {
68 httpServer
.removeContext("/" + contextName
);
73 public void setHttpServer(HttpServer httpServer
) {
74 Integer httpPort
= httpServer
.getAddress().getPort();
75 String baseUrl
= "http://localhost:" + httpPort
+ "/";
76 Path runFile
= CmsRcpDisplayFactory
.getUrlRunFile();
78 if (!Files
.exists(runFile
)) {
79 Files
.createDirectories(runFile
.getParent());
80 // TODO give read permission only to the owner
81 Files
.createFile(runFile
);
83 URI uri
= URI
.create(Files
.readString(runFile
));
84 if (!httpPort
.equals(uri
.getPort()))
85 if (!isPortAvailable(uri
.getPort())) {
86 throw new IllegalStateException("Another CMS is running on " + runFile
);
88 logger
.log(Level
.WARNING
,
89 "Run file " + runFile
+ " found but port of " + uri
+ " is available. Overwriting...");
92 Files
.writeString(runFile
, baseUrl
, StandardCharsets
.UTF_8
);
93 } catch (IOException e
) {
94 throw new RuntimeException("Cannot write run file to " + runFile
, e
);
96 logger
.log(DEBUG
, "RCP available under " + baseUrl
+ ", written to " + runFile
);
97 this.httpServer
.complete(httpServer
);
100 protected boolean isPortAvailable(int port
) {
101 ServerSocket ss
= null;
102 DatagramSocket ds
= null;
104 ss
= new ServerSocket(port
);
105 ss
.setReuseAddress(true);
106 ds
= new DatagramSocket(port
);
107 ds
.setReuseAddress(true);
109 } catch (IOException e
) {
118 } catch (IOException e
) {
119 /* should not be thrown */