/** * Copyright 2015-2016 Red Hat, Inc, and individual contributors. * * Licensed 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.wildfly.swarm.monitor.runtime; import java.util.List; import java.util.Optional; import javax.enterprise.context.ApplicationScoped; import javax.naming.NamingException; import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationTarget; import org.jboss.jandex.ClassInfo; import org.jboss.jandex.DotName; import org.jboss.jandex.Index; import org.jboss.jandex.MethodInfo; import org.jboss.shrinkwrap.api.Archive; import org.wildfly.swarm.monitor.HealthMetaData; import org.wildfly.swarm.spi.api.ArchiveMetadataProcessor; import org.wildfly.swarm.undertow.descriptors.JBossWebContainer; /** * @author Ken Finnigan */ @ApplicationScoped public class HealthAnnotationProcessor implements ArchiveMetadataProcessor { public static final DotName HEALTH = DotName.createSimple("org.wildfly.swarm.health.Health"); public static final DotName PATH = DotName.createSimple("javax.ws.rs.Path"); public static final DotName APP_PATH = DotName.createSimple("javax.ws.rs.ApplicationPath"); @Override public void processArchive(Archive<?> archive, Index index) throws NamingException { // first pass: jboss-web context root Optional<String> jbossWebContext = Optional.empty(); if (archive instanceof JBossWebContainer) { JBossWebContainer war = (JBossWebContainer) archive; if (war.getContextRoot() != null) { jbossWebContext = Optional.of(war.getContextRoot()); } } // second pass: JAX-RS applications Optional<String> appPath = Optional.empty(); List<AnnotationInstance> appPathAnnotations = index.getAnnotations(APP_PATH); for (AnnotationInstance annotation : appPathAnnotations) { if (annotation.target().kind() == AnnotationTarget.Kind.CLASS) { appPath = Optional.of(annotation.value().asString()); } } // third pass: JAX-RS resources List<AnnotationInstance> pathAnnotations = index.getAnnotations(PATH); for (AnnotationInstance annotation : pathAnnotations) { if (annotation.target().kind() == AnnotationTarget.Kind.CLASS) { ClassInfo classInfo = annotation.target().asClass(); for (MethodInfo methodInfo : classInfo.methods()) { if (methodInfo.hasAnnotation(HEALTH)) { StringBuilder sb = new StringBuilder(); boolean isSecure = false; // prepend the jboss-web cntext if given if (jbossWebContext.isPresent() && !jbossWebContext.get().equals("/")) { safeAppend(sb, jbossWebContext.get()); } // prepend the appPath if given if (appPath.isPresent() && !appPath.get().equals("/")) { safeAppend(sb, appPath.get()); } // the class level @Path for (AnnotationInstance classAnnotation : classInfo.classAnnotations()) { if (classAnnotation.name().equals(PATH)) { String methodPathValue = classAnnotation.value().asString(); if (!methodPathValue.equals("/")) { safeAppend(sb, methodPathValue); } } } if (methodInfo.hasAnnotation(PATH)) { // the method level @Path safeAppend(sb, methodInfo.annotation(PATH).value().asString()); // the method level @Health AnnotationInstance healthAnnotation = methodInfo.annotation(HEALTH); isSecure = healthAnnotation.value("inheritSecurity") != null ? healthAnnotation.value("inheritSecurity").asBoolean() : true; } else { throw new RuntimeException("@Health requires an explicit @Path annotation"); } HealthMetaData metaData = new HealthMetaData(sb.toString(), isSecure); Monitor.lookup().registerHealth(metaData); } } } } } public static void safeAppend(StringBuilder sb, String pathToken) { // normalise the token to '/foobar' if (!pathToken.startsWith("/")) { pathToken = "/" + pathToken; } if (pathToken.endsWith("/")) { pathToken = pathToken.substring(0, pathToken.length() - 1); } // append to buffer sb.append(pathToken); } }