2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
20 package org.openecomp.policy.drools.http.server.internal;
22 import org.eclipse.jetty.security.ConstraintMapping;
23 import org.eclipse.jetty.security.ConstraintSecurityHandler;
24 import org.eclipse.jetty.security.HashLoginService;
25 import org.eclipse.jetty.security.authentication.BasicAuthenticator;
26 import org.eclipse.jetty.server.Server;
27 import org.eclipse.jetty.server.ServerConnector;
28 import org.eclipse.jetty.servlet.ServletContextHandler;
29 import org.eclipse.jetty.util.security.Constraint;
30 import org.eclipse.jetty.util.security.Credential;
31 import org.openecomp.policy.drools.http.server.HttpServletServer;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
35 import com.fasterxml.jackson.annotation.JsonIgnore;
38 * Http Server implementation using Embedded Jetty
40 public abstract class JettyServletServer implements HttpServletServer, Runnable {
42 private static Logger logger = LoggerFactory.getLogger(JettyServletServer.class);
44 protected final String name;
46 protected final String host;
47 protected final int port;
49 protected String user;
50 protected String password;
52 protected final String contextPath;
54 protected final Server jettyServer;
55 protected final ServletContextHandler context;
56 protected final ServerConnector connector;
58 protected volatile Thread jettyThread;
60 protected Object startCondition = new Object();
62 public JettyServletServer(String name, String host, int port, String contextPath)
63 throws IllegalArgumentException {
65 if (name == null || name.isEmpty())
66 name = "http-" + port;
68 if (port <= 0 && port >= 65535)
69 throw new IllegalArgumentException("Invalid Port provided: " + port);
71 if (host == null || host.isEmpty())
74 if (contextPath == null || contextPath.isEmpty())
82 this.contextPath = contextPath;
84 this.context = new ServletContextHandler(ServletContextHandler.SESSIONS);
85 this.context.setContextPath(contextPath);
87 this.jettyServer = new Server();
89 this.connector = new ServerConnector(this.jettyServer);
90 this.connector.setName(name);
91 this.connector.setReuseAddress(true);
92 this.connector.setPort(port);
93 this.connector.setHost(host);
95 this.jettyServer.addConnector(this.connector);
96 this.jettyServer.setHandler(context);
103 public void setBasicAuthentication(String user, String password, String servletPath) {
104 if (user == null || user.isEmpty() || password == null || password.isEmpty())
105 throw new IllegalArgumentException("Missing user and/or password");
107 if (servletPath == null || servletPath.isEmpty())
110 HashLoginService hashLoginService = new HashLoginService();
111 hashLoginService.putUser(user,
112 Credential.getCredential(password),
113 new String[] {"user"});
114 hashLoginService.setName(this.connector.getName() + "-login-service");
116 Constraint constraint = new Constraint();
117 constraint.setName(Constraint.__BASIC_AUTH);
118 constraint.setRoles(new String[]{"user"});
119 constraint.setAuthenticate(true);
121 ConstraintMapping constraintMapping = new ConstraintMapping();
122 constraintMapping.setConstraint(constraint);
123 constraintMapping.setPathSpec(servletPath);
125 ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler();
126 securityHandler.setAuthenticator(new BasicAuthenticator());
127 securityHandler.setRealmName(this.connector.getName() + "-realm");
128 securityHandler.addConstraintMapping(constraintMapping);
129 securityHandler.setLoginService(hashLoginService);
131 this.context.setSecurityHandler(securityHandler);
134 this.password = password;
138 * Jetty Server Execution
143 logger.info("{}: STARTING", this);
145 this.jettyServer.start();
147 if (logger.isInfoEnabled())
148 logger.info("{}: STARTED: {}", this, this.jettyServer.dump());
150 synchronized(this.startCondition) {
151 this.startCondition.notifyAll();
154 this.jettyServer.join();
155 } catch (Exception e) {
156 logger.error("{}: error found while bringing up server", this, e);
161 public boolean waitedStart(long maxWaitTime) throws IllegalArgumentException {
162 logger.info("{}: WAITED-START", this);
165 throw new IllegalArgumentException("max-wait-time cannot be negative");
167 long pendingWaitTime = maxWaitTime;
172 synchronized (this.startCondition) {
174 while (!this.jettyServer.isRunning()) {
176 long startTs = System.currentTimeMillis();
178 this.startCondition.wait(pendingWaitTime);
180 if (maxWaitTime == 0)
181 /* spurious notification */
184 long endTs = System.currentTimeMillis();
185 pendingWaitTime = pendingWaitTime - (endTs - startTs);
187 logger.info("{}: pending time is {} ms.", this, pendingWaitTime);
189 if (pendingWaitTime <= 0)
192 } catch (InterruptedException e) {
193 logger.warn("{}: waited-start has been interrupted", this);
198 return (this.jettyServer.isRunning());
206 public boolean start() throws IllegalStateException {
207 logger.info("{}: STARTING", this);
210 if (jettyThread == null ||
211 !this.jettyThread.isAlive()) {
213 this.jettyThread = new Thread(this);
214 this.jettyThread.setName(this.name + "-" + this.port);
215 this.jettyThread.start();
226 public boolean stop() throws IllegalStateException {
227 logger.info("{}: STOPPING", this);
230 if (jettyThread == null) {
234 if (!jettyThread.isAlive()) {
235 this.jettyThread = null;
239 this.connector.stop();
240 } catch (Exception e) {
241 logger.error("{}: error while stopping management server", this, e);
245 this.jettyServer.stop();
246 } catch (Exception e) {
247 logger.error("{}: error while stopping management server", this, e);
261 public void shutdown() throws IllegalStateException {
262 logger.info("{}: SHUTTING DOWN", this);
266 if (this.jettyThread == null)
269 Thread jettyThreadCopy = this.jettyThread;
271 if (jettyThreadCopy.isAlive()) {
273 jettyThreadCopy.join(1000L);
274 } catch (InterruptedException e) {
275 logger.warn("{}: error while shutting down management server", this);
277 if (!jettyThreadCopy.isInterrupted()) {
279 jettyThreadCopy.interrupt();
280 } catch(Exception e) {
282 logger.warn("{}: exception while shutting down (OK)", this);
287 this.jettyServer.destroy();
294 public boolean isAlive() {
295 if (this.jettyThread != null)
296 return this.jettyThread.isAlive();
302 public int getPort() {
309 public String getName() {
316 public String getHost() {
323 public String getUser() {
328 * @return the password
331 public String getPassword() {
336 public String toString() {
337 StringBuilder builder = new StringBuilder();
338 builder.append("JettyServer [name=").append(name).append(", host=").append(host).append(", port=").append(port)
339 .append(", user=").append(user).append(", password=").append((password != null)).append(", contextPath=")
340 .append(contextPath).append(", jettyServer=").append(jettyServer).append(", context=").append(this.context)
341 .append(", connector=").append(connector).append(", jettyThread=").append(jettyThread)
343 return builder.toString();