001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.microservice.jetty; 014 015import java.io.*; 016import java.util.*; 017import java.util.logging.*; 018 019import javax.servlet.*; 020 021import org.apache.juneau.*; 022import org.apache.juneau.config.*; 023import org.apache.juneau.config.store.*; 024import org.apache.juneau.internal.*; 025import org.apache.juneau.microservice.*; 026import org.apache.juneau.microservice.console.*; 027import org.apache.juneau.rest.*; 028import org.apache.juneau.rest.annotation.*; 029import org.apache.juneau.svl.*; 030import org.apache.juneau.utils.*; 031import org.eclipse.jetty.server.*; 032 033/** 034 * Builder for {@link JettyMicroservice} class. 035 * 036 * <p> 037 * Instances of this class are created using {@link JettyMicroservice#create()}. 038 */ 039public class JettyMicroserviceBuilder extends MicroserviceBuilder { 040 041 String jettyXml; 042 int[] ports; 043 Boolean jettyXmlResolveVars; 044 Map<String,Servlet> servlets = new LinkedHashMap<>(); 045 Map<String,Object> servletAttributes = new LinkedHashMap<>(); 046 JettyMicroserviceListener listener; 047 JettyServerFactory factory; 048 049 /** 050 * Constructor. 051 */ 052 protected JettyMicroserviceBuilder() {} 053 054 /** 055 * Copy constructor. 056 * 057 * @param copyFrom The builder to copy settings from. 058 */ 059 protected JettyMicroserviceBuilder(JettyMicroserviceBuilder copyFrom) { 060 super(copyFrom); 061 this.jettyXml = copyFrom.jettyXml; 062 this.ports = copyFrom.ports; 063 this.jettyXmlResolveVars = copyFrom.jettyXmlResolveVars; 064 this.servlets = new LinkedHashMap<>(copyFrom.servlets); 065 this.servletAttributes = new LinkedHashMap<>(copyFrom.servletAttributes); 066 this.listener = copyFrom.listener; 067 } 068 069 @Override /* MicroserviceBuilder */ 070 public JettyMicroserviceBuilder copy() { 071 return new JettyMicroserviceBuilder(this); 072 } 073 074 /** 075 * Specifies the contents or location of the <code>jetty.xml</code> file used by the Jetty server. 076 * 077 * <p> 078 * If you do not specify this value, it is pulled from the following in the specified order: 079 * <ul class='spaced-list'> 080 * <li> 081 * <code>Jetty/config</code> setting in the config file. 082 * <code>Jetty-Config</code> setting in the manifest file. 083 * </ul> 084 * 085 * <p> 086 * By default, we look for the <code>jetty.xml</code> file in the following locations: 087 * <ul class='spaced-list'> 088 * <li><code>jetty.xml</code> in home directory. 089 * <li><code>files/jetty.xml</code> in home directory. 090 * <li><code>/jetty.xml</code> in classpath. 091 * <li><code>/files/jetty.xml</code> in classpath. 092 * </ul> 093 * 094 * @param jettyXml 095 * The contents or location of the file. 096 * <br>Can be any of the following: 097 * <ul> 098 * <li>{@link String} - Relative path to file on file system or classpath. 099 * <li>{@link File} - File on file system. 100 * <li>{@link InputStream} - Raw contents as <code>UTF-8</code> encoded stream. 101 * <li>{@link Reader} - Raw contents. 102 * </ul> 103 * 104 * @param resolveVars 105 * If <jk>true</jk>, SVL variables in the file will automatically be resolved. 106 * @return This object (for method chaining). 107 * @throws IOException 108 */ 109 public JettyMicroserviceBuilder jettyXml(Object jettyXml, boolean resolveVars) throws IOException { 110 if (jettyXml instanceof String) 111 this.jettyXml = IOUtils.read(new File(jettyXml.toString())); 112 else if (jettyXml instanceof File) 113 this.jettyXml = IOUtils.read((File)jettyXml); 114 else if (jettyXml instanceof InputStream) 115 this.jettyXml = IOUtils.read((InputStream)jettyXml); 116 else if (jettyXml instanceof Reader) 117 this.jettyXml = IOUtils.read((Reader)jettyXml); 118 else 119 throw new FormattedRuntimeException("Invalid object type passed to jettyXml(Object)", jettyXml == null ? null : jettyXml.getClass().getName()); 120 this.jettyXmlResolveVars = resolveVars; 121 return this; 122 } 123 124 /** 125 * Specifies the ports to use for the web server. 126 * 127 * <p> 128 * You can specify multiple ports. The first available will be used. <js>'0'</js> indicates to try a random port. 129 * The resulting available port gets set as the system property <js>"availablePort"</js> which can be referenced in the 130 * <code>jetty.xml</code> file as <js>"$S{availablePort}"</js> (assuming resolveVars is enabled). 131 * 132 * <p> 133 * If you do not specify this value, it is pulled from the following in the specified order: 134 * <ul class='spaced-list'> 135 * <li> 136 * <code>Jetty/port</code> setting in the config file. 137 * <li> 138 * <code>Jetty-Port</code> setting in the manifest file. 139 * <li> 140 * <code>8000</code> 141 * </ul> 142 * 143 * Jetty/port", mf.getWithDefault("Jetty-Port", new int[]{8000} 144 * @param ports The ports to use for the web server. 145 * @return This object (for method chaining). 146 */ 147 public JettyMicroserviceBuilder ports(int...ports) { 148 this.ports = ports; 149 return this; 150 } 151 152 /** 153 * Adds a servlet to the servlet container. 154 * 155 * <p> 156 * This method can only be used with servlets with no-arg constructors. 157 * <br>The path is pulled from the {@link RestResource#path()} annotation. 158 * 159 * @param c The servlet to add to the servlet container. 160 * @return This object (for method chaining). 161 * @throws InstantiationException 162 * @throws IllegalAccessException 163 */ 164 public JettyMicroserviceBuilder servlet(Class<? extends RestServlet> c) throws InstantiationException, IllegalAccessException { 165 RestServlet rs = c.newInstance(); 166 return servlet(rs, '/' + rs.getPath()); 167 } 168 169 /** 170 * Adds a servlet to the servlet container. 171 * 172 * <p> 173 * This method can only be used with servlets with no-arg constructors. 174 * 175 * @param c The servlet to add to the servlet container. 176 * @param path The servlet path spec. 177 * @return This object (for method chaining). 178 * @throws InstantiationException 179 * @throws IllegalAccessException 180 */ 181 public JettyMicroserviceBuilder servlet(Class<? extends Servlet> c, String path) throws InstantiationException, IllegalAccessException { 182 return servlet(c.newInstance(), path); 183 } 184 185 /** 186 * Adds a servlet instance to the servlet container. 187 * 188 * @param servlet The servlet to add to the servlet container. 189 * @param path The servlet path spec. 190 * @return This object (for method chaining). 191 */ 192 public JettyMicroserviceBuilder servlet(Servlet servlet, String path) { 193 servlets.put(path, servlet); 194 return this; 195 } 196 197 /** 198 * Adds a set of servlets to the servlet container. 199 * 200 * @param servlets 201 * A map of servlets to add to the servlet container. 202 * <br>Keys are path specs for the servlet. 203 * @return This object (for method chaining). 204 */ 205 public JettyMicroserviceBuilder servlets(Map<String,Servlet> servlets) { 206 if (servlets != null) 207 this.servlets.putAll(servlets); 208 return this; 209 } 210 211 /** 212 * Adds a servlet attribute to the servlet container. 213 * 214 * @param name The attribute name. 215 * @param value The attribute value. 216 * @return This object (for method chaining). 217 */ 218 public JettyMicroserviceBuilder servletAttribute(String name, Object value) { 219 this.servletAttributes.put(name, value); 220 return this; 221 } 222 223 /** 224 * Adds a set of servlet attributes to the servlet container. 225 * 226 * @param values The map of attributes. 227 * @return This object (for method chaining). 228 */ 229 public JettyMicroserviceBuilder servletAttribute(Map<String,Object> values) { 230 if (values != null) 231 this.servletAttributes.putAll(values); 232 return this; 233 } 234 235 /** 236 * Specifies the factory to use for creating the Jetty {@link Server} instance. 237 * 238 * <p> 239 * If not specified, uses {@link BasicJettyServerFactory}. 240 * 241 * @param value 242 * @return This object (for method chaining). 243 */ 244 public JettyMicroserviceBuilder jettyServerFactory(JettyServerFactory value) { 245 this.factory = value; 246 return this; 247 } 248 249 //----------------------------------------------------------------------------------------------------------------- 250 // Inherited from MicroserviceBuilder 251 //----------------------------------------------------------------------------------------------------------------- 252 253 @Override /* MicroserviceBuilder */ 254 public JettyMicroservice build() throws Exception { 255 return new JettyMicroservice(this); 256 } 257 258 @Override /* MicroserviceBuilder */ 259 public JettyMicroserviceBuilder args(Args args) { 260 super.args(args); 261 return this; 262 } 263 264 @Override /* MicroserviceBuilder */ 265 public JettyMicroserviceBuilder args(String...args) { 266 super.args(args); 267 return this; 268 } 269 270 @Override /* MicroserviceBuilder */ 271 public JettyMicroserviceBuilder manifest(Object manifest) throws IOException { 272 super.manifest(manifest); 273 return this; 274 } 275 276 @Override /* MicroserviceBuilder */ 277 public JettyMicroserviceBuilder logger(Logger logger) { 278 super.logger(logger); 279 return this; 280 } 281 282 283 @Override /* MicroserviceBuilder */ 284 public JettyMicroserviceBuilder logConfig(LogConfig logConfig) { 285 return this; 286 } 287 288 @Override /* MicroserviceBuilder */ 289 public JettyMicroserviceBuilder config(Config config) { 290 super.config(config); 291 return this; 292 } 293 294 @Override /* MicroserviceBuilder */ 295 public JettyMicroserviceBuilder configName(String configName) { 296 super.configName(configName); 297 return this; 298 } 299 300 @Override /* MicroserviceBuilder */ 301 public JettyMicroserviceBuilder configStore(ConfigStore configStore) { 302 super.configStore(configStore); 303 return this; 304 } 305 306 @Override /* MicroserviceBuilder */ 307 public JettyMicroserviceBuilder consoleEnabled(boolean consoleEnabled) { 308 super.consoleEnabled(consoleEnabled); 309 return this; 310 } 311 312 @Override /* MicroserviceBuilder */ 313 public JettyMicroserviceBuilder consoleCommands(ConsoleCommand...consoleCommands) { 314 super.consoleCommands(consoleCommands); 315 return this; 316 } 317 318 @Override /* MicroserviceBuilder */ 319 public JettyMicroserviceBuilder console(Scanner consoleReader, PrintWriter consoleWriter) { 320 super.console(consoleReader, consoleWriter); 321 return this; 322 } 323 324 @Override /* MicroserviceBuilder */ 325 @SuppressWarnings("unchecked") 326 public JettyMicroserviceBuilder vars(Class<? extends Var>...vars) { 327 super.vars(vars); 328 return this; 329 } 330 331 @Override /* MicroserviceBuilder */ 332 public JettyMicroserviceBuilder varContext(String name, Object object) { 333 super.varContext(name, object); 334 return this; 335 } 336 337 /** 338 * Registers an event listener for this microservice. 339 * 340 * @param listener An event listener for this microservice. 341 * @return This object (for method chaining). 342 */ 343 public JettyMicroserviceBuilder listener(JettyMicroserviceListener listener) { 344 super.listener(listener); 345 this.listener = listener; 346 return this; 347 } 348}