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();