]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsDeploymentImpl.java
Fix IPA initialisation
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / internal / runtime / CmsDeploymentImpl.java
1 package org.argeo.cms.internal.runtime;
2
3 import static org.argeo.api.cms.CmsConstants.CONTEXT_PATH;
4
5 import java.util.Map;
6 import java.util.Objects;
7 import java.util.TreeMap;
8 import java.util.concurrent.CompletableFuture;
9 import java.util.concurrent.CompletionStage;
10
11 import org.argeo.api.cms.CmsConstants;
12 import org.argeo.api.cms.CmsDeployment;
13 import org.argeo.api.cms.CmsLog;
14 import org.argeo.api.cms.CmsSshd;
15 import org.argeo.api.cms.CmsState;
16 import org.argeo.cms.CmsDeployProperty;
17 import org.argeo.cms.internal.http.CmsAuthenticator;
18 import org.argeo.cms.internal.http.PublicCmsAuthenticator;
19
20 import com.sun.net.httpserver.HttpContext;
21 import com.sun.net.httpserver.HttpHandler;
22 import com.sun.net.httpserver.HttpServer;
23
24 /** Reference implementation of {@link CmsDeployment}. */
25 public class CmsDeploymentImpl implements CmsDeployment {
26 private final CmsLog log = CmsLog.getLog(getClass());
27
28 private CmsState cmsState;
29
30 // Expectations
31 private boolean httpExpected = false;
32 private boolean sshdExpected = false;
33
34 // HTTP
35 private CompletableFuture<HttpServer> httpServer = new CompletableFuture<>();
36 private Map<String, HttpHandler> httpHandlers = new TreeMap<>();
37 private Map<String, CmsAuthenticator> httpAuthenticators = new TreeMap<>();
38
39 // SSHD
40 private CompletableFuture<CmsSshd> cmsSshd = new CompletableFuture<>();
41
42 public void start() {
43 log.debug(() -> "CMS deployment available");
44 }
45
46 public void stop() {
47 }
48
49 public void setCmsState(CmsState cmsState) {
50 this.cmsState = cmsState;
51
52 String httpPort = this.cmsState.getDeployProperty(CmsDeployProperty.HTTP_PORT.getProperty());
53 String httpsPort = this.cmsState.getDeployProperty(CmsDeployProperty.HTTPS_PORT.getProperty());
54 httpExpected = httpPort != null || httpsPort != null;
55 if (!httpExpected)
56 httpServer.complete(null);
57
58 String sshdPort = this.cmsState.getDeployProperty(CmsDeployProperty.SSHD_PORT.getProperty());
59 sshdExpected = sshdPort != null;
60 if (!sshdExpected)
61 cmsSshd.complete(null);
62 }
63
64 public void setHttpServer(HttpServer httpServer) {
65 Objects.requireNonNull(httpServer);
66 if (this.httpServer.isDone())
67 if (httpExpected)
68 throw new IllegalStateException("HTTP server is already set");
69 else
70 return;// ignore
71 // create contexts whose handlers had already been published
72 synchronized (httpHandlers) {
73 synchronized (httpAuthenticators) {
74 this.httpServer.complete(httpServer);
75 for (String contextPath : httpHandlers.keySet()) {
76 HttpHandler httpHandler = httpHandlers.get(contextPath);
77 CmsAuthenticator authenticator = httpAuthenticators.get(contextPath);
78 createHttpContext(contextPath, httpHandler, authenticator);
79 }
80 }
81 }
82 }
83
84 public void addHttpHandler(HttpHandler httpHandler, Map<String, String> properties) {
85 final String contextPath = properties.get(CONTEXT_PATH);
86 if (contextPath == null) {
87 log.warn("Property " + CONTEXT_PATH + " not set on HTTP handler " + properties + ". Ignoring it.");
88 return;
89 }
90 boolean isPublic = Boolean.parseBoolean(properties.get(CmsConstants.CONTEXT_PUBLIC));
91 CmsAuthenticator authenticator = isPublic ? new PublicCmsAuthenticator() : new CmsAuthenticator();
92 synchronized (httpHandlers) {
93 synchronized (httpAuthenticators) {
94 httpHandlers.put(contextPath, httpHandler);
95 httpAuthenticators.put(contextPath, authenticator);
96 }
97 }
98 if (!httpServer.isDone()) {
99 return;
100 } else {
101 createHttpContext(contextPath, httpHandler, authenticator);
102 }
103 }
104
105 public void createHttpContext(String contextPath, HttpHandler httpHandler, CmsAuthenticator authenticator) {
106 if (!httpExpected) {
107 if (log.isTraceEnabled())
108 log.warn("Ignore HTTP context " + contextPath + " as we don't provide an HTTP server");
109 return;
110 }
111 if (!this.httpServer.isDone())
112 throw new IllegalStateException("HTTP server is not set");
113 // TODO use resultNow when switching to Java 21
114 HttpContext httpContext = httpServer.join().createContext(contextPath);
115 // we want to set the authenticator BEFORE the handler actually becomes active
116 httpContext.setAuthenticator(authenticator);
117 httpContext.setHandler(httpHandler);
118 log.debug(() -> "Added handler " + contextPath + " : " + httpHandler.getClass().getName());
119 }
120
121 public void removeHttpHandler(HttpHandler httpHandler, Map<String, String> properties) {
122 final String contextPath = properties.get(CmsConstants.CONTEXT_PATH);
123 if (contextPath == null)
124 return; // ignore silently
125 httpHandlers.remove(contextPath);
126 if (!httpExpected || !httpServer.isDone())
127 return;
128 // TODO use resultNow when switching to Java 21
129 httpServer.join().removeContext(contextPath);
130 log.debug(() -> "Removed handler " + contextPath + " : " + httpHandler.getClass().getName());
131 }
132
133 public boolean allExpectedServicesAvailable() {
134 if (httpExpected && !httpServer.isDone())
135 return false;
136 if (sshdExpected && !cmsSshd.isDone())
137 return false;
138 return true;
139 }
140
141 public void setCmsSshd(CmsSshd cmsSshd) {
142 Objects.requireNonNull(cmsSshd);
143 this.cmsSshd.complete(cmsSshd);
144 }
145
146 @Override
147 public CompletionStage<HttpServer> getHttpServer() {
148 return httpServer.minimalCompletionStage();
149 }
150
151 @Override
152 public CompletionStage<CmsSshd> getCmsSshd() {
153 return cmsSshd.minimalCompletionStage();
154 }
155
156 }