/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jooby.internal;
import static javaslang.API.$;
import static javaslang.API.Case;
import static javaslang.API.Match;
import static javaslang.Predicates.instanceOf;
import java.util.Set;
import java.util.function.Function;
import org.jooby.Route;
import org.jooby.WebSocket;
import org.slf4j.Logger;
import com.google.common.base.Strings;
import com.typesafe.config.Config;
public class AppPrinter {
private Set<Route.Definition> routes;
private Set<WebSocket.Definition> sockets;
private String[] urls;
private boolean http2;
private boolean h2cleartext;
public AppPrinter(final Set<Route.Definition> routes,
final Set<WebSocket.Definition> sockets,
final Config conf) {
this.routes = routes;
this.sockets = sockets;
String host = conf.getString("application.host");
String port = conf.getString("application.port");
String path = conf.getString("application.path");
this.urls = new String[2];
this.urls[0] = "http://" + host + ":" + port + path;
if (conf.hasPath("application.securePort")) {
this.urls[1] = "https://" + host + ":" + conf.getString("application.securePort") + path;
}
http2 = conf.getBoolean("server.http2.enabled");
h2cleartext = conf.getBoolean("server.http2.cleartext");
}
public void printConf(final Logger log, final Config conf) {
if (log.isDebugEnabled()) {
String desc = configTree(conf.origin().description());
log.debug("config tree:\n{}", desc);
}
}
private String configTree(final String description) {
return configTree(description.split(":\\s+\\d+,|,"), 0);
}
private String configTree(final String[] sources, final int i) {
if (i < sources.length) {
return new StringBuilder()
.append(Strings.padStart("", i, ' '))
.append("└── ")
.append(sources[i])
.append("\n")
.append(configTree(sources, i + 1))
.toString();
}
return "";
}
@Override
public String toString() {
StringBuilder buffer = new StringBuilder();
routes(buffer);
String[] h2 = {h2(" ", http2 && h2cleartext), h2("", http2) };
buffer.append("\nlistening on:");
for (int i = 0; i < urls.length; i++) {
if (urls[i] != null) {
buffer.append("\n ").append(urls[i]).append(h2[i]);
}
}
return buffer.toString();
}
private String h2(final String prefix, final boolean h2) {
return h2 ? prefix + " +h2" : "";
}
private void routes(final StringBuilder buffer) {
Function<Route.Definition, String> p = route -> {
return Match(route.filter()).of(
Case(instanceOf(Route.Before.class), "{before}" + route.pattern()),
Case(instanceOf(Route.After.class), "{after}" + route.pattern()),
Case(instanceOf(Route.Complete.class), "{complete}" + route.pattern()),
Case($(), route.pattern()));
};
int verbMax = 0, routeMax = 0, consumesMax = 0, producesMax = 0;
for (Route.Definition route : routes) {
verbMax = Math.max(verbMax, route.method().length());
routeMax = Math.max(routeMax, p.apply(route).length());
consumesMax = Math.max(consumesMax, route.consumes().toString().length());
producesMax = Math.max(producesMax, route.produces().toString().length());
}
String format = " %-" + verbMax + "s %-" + routeMax + "s %" + consumesMax
+ "s %" + producesMax + "s (%s)\n";
for (Route.Definition route : routes) {
buffer.append(
String.format(format, route.method(), p.apply(route), route.consumes(),
route.produces(), route.name()));
}
sockets(buffer, Math.max(verbMax, "WS".length()), routeMax, consumesMax, producesMax);
}
private void sockets(final StringBuilder buffer, final int verbMax, int routeMax,
int consumesMax, int producesMax) {
for (WebSocket.Definition socket : sockets) {
routeMax = Math.max(routeMax, socket.pattern().length());
consumesMax = Math.max(consumesMax, socket.consumes().toString().length() + 2);
producesMax = Math.max(producesMax, socket.produces().toString().length() + 2);
}
String format = " %-" + verbMax + "s %-" + routeMax + "s %" + consumesMax + "s %"
+ producesMax + "s\n";
for (WebSocket.Definition socket : sockets) {
buffer.append(String.format(format, "WS", socket.pattern(),
"[" + socket.consumes() + "]", "[" + socket.produces() + "]"));
}
}
}