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;
32 import org.openecomp.policy.common.logging.eelf.MessageCodes;
33 import org.openecomp.policy.common.logging.flexlogger.FlexLogger;
34 import org.openecomp.policy.common.logging.flexlogger.Logger;
35 import org.openecomp.policy.drools.http.server.HttpServletServer;
37 import com.fasterxml.jackson.annotation.JsonIgnore;
40 * Http Server implementation using Embedded Jetty
42 public abstract class JettyServletServer implements HttpServletServer, Runnable {
44 private static Logger logger = FlexLogger.getLogger(JettyServletServer.class);
46 protected final String name;
48 protected final String host;
49 protected final int port;
51 protected String user;
52 protected String password;
54 protected final String contextPath;
56 protected final Server jettyServer;
57 protected final ServletContextHandler context;
58 protected final ServerConnector connector;
60 protected volatile Thread jettyThread;
62 protected Object startCondition = new Object();
64 public JettyServletServer(String name, String host, int port, String contextPath)
65 throws IllegalArgumentException {
67 if (name == null || name.isEmpty())
68 name = "http-" + port;
70 if (port <= 0 && port >= 65535)
71 throw new IllegalArgumentException("Invalid Port provided: " + port);
73 if (host == null || host.isEmpty())
76 if (contextPath == null || contextPath.isEmpty())
84 this.contextPath = contextPath;
86 this.context = new ServletContextHandler(ServletContextHandler.SESSIONS);
87 this.context.setContextPath(contextPath);
89 this.jettyServer = new Server();
91 this.connector = new ServerConnector(this.jettyServer);
92 this.connector.setName(name);
93 this.connector.setReuseAddress(true);
94 this.connector.setPort(port);
95 this.connector.setHost(host);
97 this.jettyServer.addConnector(this.connector);
98 this.jettyServer.setHandler(context);
105 public void setBasicAuthentication(String user, String password, String servletPath) {
106 if (user == null || user.isEmpty() || password == null || password.isEmpty())
107 throw new IllegalArgumentException("Missing user and/or password");
109 if (servletPath == null || servletPath.isEmpty())
112 HashLoginService hashLoginService = new HashLoginService();
113 hashLoginService.putUser(user,
114 Credential.getCredential(password),
115 new String[] {"user"});
116 hashLoginService.setName(this.connector.getName() + "-login-service");
118 Constraint constraint = new Constraint();
119 constraint.setName(Constraint.__BASIC_AUTH);
120 constraint.setRoles(new String[]{"user"});
121 constraint.setAuthenticate(true);
123 ConstraintMapping constraintMapping = new ConstraintMapping();
124 constraintMapping.setConstraint(constraint);
125 constraintMapping.setPathSpec(servletPath);
127 ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler();
128 securityHandler.setAuthenticator(new BasicAuthenticator());
129 securityHandler.setRealmName(this.connector.getName() + "-realm");
130 securityHandler.addConstraintMapping(constraintMapping);
131 securityHandler.setLoginService(hashLoginService);
133 this.context.setSecurityHandler(securityHandler);
136 this.password = password;
140 * Jetty Server Execution
145 if (logger.isInfoEnabled())
146 logger.info(this + " STARTING " + this.jettyServer.dump());
148 this.jettyServer.start();
150 synchronized(this.startCondition) {
151 this.startCondition.notifyAll();
154 this.jettyServer.join();
155 } catch (Exception e) {
156 logger.warn(MessageCodes.EXCEPTION_ERROR, e,
157 "Error found while running management server", this.toString());
162 public boolean waitedStart(long maxWaitTime) throws IllegalArgumentException {
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 if (logger.isInfoEnabled())
188 logger.info(this + "Pending time is " + pendingWaitTime +
191 if (pendingWaitTime <= 0)
194 } catch (InterruptedException e) {
195 logger.warn("waited-start has been interrupted");
200 return (this.jettyServer.isRunning());
208 public boolean start() throws IllegalStateException {
209 if (logger.isDebugEnabled())
210 logger.debug(this + "START");
213 if (jettyThread == null ||
214 !this.jettyThread.isAlive()) {
216 this.jettyThread = new Thread(this);
217 this.jettyThread.setName(this.name + "-" + this.port);
218 this.jettyThread.start();
229 public boolean stop() throws IllegalStateException {
230 logger.info(this + "STOP");
233 if (jettyThread == null) {
237 if (!jettyThread.isAlive()) {
238 this.jettyThread = null;
242 this.connector.stop();
243 } catch (Exception e) {
244 logger.error(MessageCodes.EXCEPTION_ERROR, e,
245 "Error while stopping management server", this.toString());
250 this.jettyServer.stop();
251 } catch (Exception e) {
252 logger.error(MessageCodes.EXCEPTION_ERROR, e,
253 "Error while stopping management server", this.toString());
267 public void shutdown() throws IllegalStateException {
268 logger.info(this + "SHUTDOWN");
272 if (this.jettyThread == null)
275 Thread jettyThreadCopy = this.jettyThread;
277 if (jettyThreadCopy.isAlive()) {
279 jettyThreadCopy.join(1000L);
280 } catch (InterruptedException e) {
281 logger.warn(MessageCodes.EXCEPTION_ERROR, e,
282 "Error while shutting down management server", this.toString());
284 if (!jettyThreadCopy.isInterrupted()) {
286 jettyThreadCopy.interrupt();
287 } catch(Exception e) {
289 logger.warn("exception while shutting down (OK)");
294 this.jettyServer.destroy();
301 public boolean isAlive() {
302 if (this.jettyThread != null)
303 return this.jettyThread.isAlive();
309 public int getPort() {
316 public String getName() {
323 public String getHost() {
330 public String getUser() {
335 * @return the password
338 public String getPassword() {
343 public String toString() {
344 StringBuilder builder = new StringBuilder();
345 builder.append("JettyServer [name=").append(name).append(", host=").append(host).append(", port=").append(port)
346 .append(", user=").append(user).append(", password=").append((password != null)).append(", contextPath=")
347 .append(contextPath).append(", jettyServer=").append(jettyServer).append(", context=").append(this.context)
348 .append(", connector=").append(connector).append(", jettyThread=").append(jettyThread)
350 return builder.toString();