2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017-2019 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=========================================================
21 package org.onap.policy.common.endpoints.http.server.internal;
23 import io.swagger.jersey.config.JerseyJaxrsConfig;
24 import java.util.HashMap;
25 import org.eclipse.jetty.servlet.ServletHolder;
26 import org.glassfish.jersey.server.ServerProperties;
27 import org.onap.policy.common.utils.network.NetworkUtil;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
32 * REST Jetty Server that uses Jersey Servlets to support JAX-RS Web Services.
34 * <p>Note: the serialization provider will always be added to the server's class providers,
35 * as will the swagger providers (assuming swagger has been enabled). This happens whether
36 * {@link #addServletClass(String, String)} is used or
37 * {@link #addServletPackage(String, String)} is used. Thus it's possible to have both the
38 * server's class provider property and the server's package provider property populated.
40 * <p>Also note: the serialization provider will be ignored if the maven artifact,
41 * <i>jersey-media-json-jackson</i>, is included, regardless of whether it's included
42 * directly or indirectly.
44 public class JettyJerseyServer extends JettyServletServer {
47 * Swagger API Base Path.
49 protected static final String SWAGGER_API_BASEPATH = "swagger.api.basepath";
54 protected static final String SWAGGER_CONTEXT_ID = "swagger.context.id";
59 protected static final String SWAGGER_SCANNER_ID = "swagger.scanner.id";
62 * Swagger Pretty Print.
64 protected static final String SWAGGER_PRETTY_PRINT = "swagger.pretty.print";
67 * Jersey Jackson Classes Init Param Value.
69 protected static final String JERSEY_JACKSON_INIT_CLASSNAMES_PARAM_VALUE =
70 "com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider";
73 * Jersey Swagger Classes Init Param Value.
75 protected static final String SWAGGER_INIT_CLASSNAMES_PARAM_VALUE =
76 "io.swagger.jaxrs.listing.ApiListingResource," + "io.swagger.jaxrs.listing.SwaggerSerializers";
80 protected static Logger logger = LoggerFactory.getLogger(JettyJerseyServer.class);
83 * Container for servlets.
85 protected HashMap<String, ServletHolder> servlets = new HashMap<>();
90 protected String swaggerId = null;
93 * The serialization provider to be used when classes are added to the service.
95 private String classProvider = JERSEY_JACKSON_INIT_CLASSNAMES_PARAM_VALUE;
101 * @param https enable https?
102 * @param host host server host
103 * @param port port server port
104 * @param swagger support swagger?
105 * @param contextPath context path
107 * @throws IllegalArgumentException in invalid arguments are provided
109 public JettyJerseyServer(String name, boolean https, String host, int port, String contextPath, boolean swagger) {
111 super(name, https, host, port, contextPath);
113 this.swaggerId = "swagger-" + this.port;
114 attachSwaggerServlet(https);
119 * Attaches a swagger initialization servlet.
121 protected void attachSwaggerServlet(boolean https) {
123 ServletHolder swaggerServlet = context.addServlet(JerseyJaxrsConfig.class, "/");
125 String hostname = this.connector.getHost();
126 if (hostname == null || hostname.isEmpty() || hostname.equals(NetworkUtil.IPv4_WILDCARD_ADDRESS)) {
127 hostname = NetworkUtil.getHostname();
130 swaggerServlet.setInitParameter(SWAGGER_API_BASEPATH,
131 ((https) ? "https://" : "http://") + hostname + ":" + this.connector.getPort() + "/");
132 swaggerServlet.setInitParameter(SWAGGER_CONTEXT_ID, swaggerId);
133 swaggerServlet.setInitParameter(SWAGGER_SCANNER_ID, swaggerId);
134 swaggerServlet.setInitParameter(SWAGGER_PRETTY_PRINT, "true");
135 swaggerServlet.setInitOrder(2);
137 if (logger.isDebugEnabled()) {
138 logger.debug("{}: Swagger Servlet has been attached: {}", this, swaggerServlet.dump());
143 * Retrieves cached server based on servlet path.
145 * @param servletPath servlet path
146 * @return the jetty servlet holder
148 * @throws IllegalArgumentException if invalid arguments are provided
150 protected synchronized ServletHolder getServlet(String servletPath) {
152 ServletHolder jerseyServlet = servlets.get(servletPath);
153 if (jerseyServlet == null) {
154 jerseyServlet = context.addServlet(org.glassfish.jersey.servlet.ServletContainer.class, servletPath);
155 jerseyServlet.setInitOrder(0);
156 servlets.put(servletPath, jerseyServlet);
159 return jerseyServlet;
163 public synchronized void addServletPackage(String servletPath, String restPackage) {
164 String servPath = servletPath;
165 if (restPackage == null || restPackage.isEmpty()) {
166 throw new IllegalArgumentException("No discoverable REST package provided");
169 if (servPath == null || servPath.isEmpty()) {
173 ServletHolder jerseyServlet = this.getServlet(servPath);
175 initStandardParams(jerseyServlet);
177 String initPackages = jerseyServlet.getInitParameter(ServerProperties.PROVIDER_PACKAGES);
178 if (initPackages == null) {
179 initPackages = restPackage;
182 initPackages += "," + restPackage;
185 jerseyServlet.setInitParameter(ServerProperties.PROVIDER_PACKAGES, initPackages);
187 if (logger.isDebugEnabled()) {
188 logger.debug("{}: added REST package: {}", this, jerseyServlet.dump());
193 public synchronized void addServletClass(String servletPath, String restClass) {
195 if (restClass == null || restClass.isEmpty()) {
196 throw new IllegalArgumentException("No discoverable REST class provided");
199 if (servletPath == null || servletPath.isEmpty()) {
203 ServletHolder jerseyServlet = this.getServlet(servletPath);
205 initStandardParams(jerseyServlet);
207 String initClasses = jerseyServlet.getInitParameter(ServerProperties.PROVIDER_CLASSNAMES);
208 if (initClasses == null) {
209 initClasses = restClass;
212 initClasses += "," + restClass;
215 jerseyServlet.setInitParameter(ServerProperties.PROVIDER_CLASSNAMES, initClasses);
217 if (logger.isDebugEnabled()) {
218 logger.debug("{}: added REST class: {}", this, jerseyServlet.dump());
223 * Adds "standard" parameters to the initParameter set. Sets swagger parameters, if
224 * specified, and sets the class provider property. This can be invoked multiple
225 * times, but only the first actually causes any changes to the parameter set.
227 * @param jerseyServlet servlet into which parameters should be added
229 private void initStandardParams(ServletHolder jerseyServlet) {
230 String initClasses = jerseyServlet.getInitParameter(ServerProperties.PROVIDER_CLASSNAMES);
231 if (initClasses != null) {
235 initClasses = classProvider;
237 if (this.swaggerId != null) {
238 initClasses += "," + SWAGGER_INIT_CLASSNAMES_PARAM_VALUE;
240 jerseyServlet.setInitParameter(SWAGGER_CONTEXT_ID, swaggerId);
241 jerseyServlet.setInitParameter(SWAGGER_SCANNER_ID, swaggerId);
244 jerseyServlet.setInitParameter(ServerProperties.PROVIDER_CLASSNAMES, initClasses);
246 jerseyServlet.setInitParameter(ServerProperties.METAINF_SERVICES_LOOKUP_DISABLE, "true");
250 * Note: this must be invoked <i>before</i> {@link #addServletClass(String, String)}
251 * or {@link #addServletPackage(String, String)}.
254 public void setSerializationProvider(String provider) {
255 classProvider = provider;
259 public String toString() {
260 StringBuilder builder = new StringBuilder();
261 builder.append("JettyJerseyServer [servlets=").append(servlets).append(", swaggerId=").append(swaggerId)
262 .append(", toString()=").append(super.toString()).append("]");
263 return builder.toString();