
org.jboss.weld.probe.Reports Maven / Gradle / Ivy
/*
* JBoss, Home of Professional Open Source
* Copyright 2017, Red Hat, Inc., and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of 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.jboss.weld.probe;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.security.AccessController;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.enterprise.inject.AmbiguousResolutionException;
import javax.enterprise.inject.Any;
import javax.enterprise.inject.Default;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.InjectionPoint;
import org.jboss.weld.Container;
import org.jboss.weld.bootstrap.api.Environment;
import org.jboss.weld.bootstrap.spi.BeanDeploymentArchive;
import org.jboss.weld.bootstrap.spi.BeanDiscoveryMode;
import org.jboss.weld.bootstrap.spi.BeansXml;
import org.jboss.weld.config.ConfigurationKey;
import org.jboss.weld.config.Description;
import org.jboss.weld.config.WeldConfiguration;
import org.jboss.weld.manager.BeanManagerImpl;
import org.jboss.weld.probe.Components.BeanKind;
import org.jboss.weld.probe.HtmlTag.SafeString;
import org.jboss.weld.security.GetSystemPropertyAction;
import org.jboss.weld.util.reflection.Formats;
/**
*
* @author Martin Kouba
*/
class Reports {
private static final String VALIDATION_REPORT_FILE_NAME = "weld-validation-report.html";
private static final String TITLE = "Weld - Validation Report";
private static final String TITLE_EXCEPTION = "Validation Issue";
private static final String TITLE_BDAS = "Deployment - Bean Archives";
private static final String TITLE_DEPS = "Dependency Issues";
private static final String TITLE_CONFIG = "Weld Configuration - Modified Values";
private static final String TITLE_BEANS = "Enabled Beans";
private static final String EXCEPTION = "exception";
private static final String BDAS = "bdas";
private static final String DEPS = "deps";
private static final String CONFIG = "config";
private static final String BEANS = "beans";
private Reports() {
}
static void generateValidationReport(Probe probe, Exception exception, Environment environment, BeanManagerImpl manager) {
HtmlTag html = HtmlTag.html();
HtmlTag head = HtmlTag.head().appendTo(html);
head.add(HtmlTag.title(TITLE));
head.add(HtmlTag.style().add(SafeString.of(IOUtils.getResourceAsString("/report.css"))));
HtmlTag body = HtmlTag.body().appendTo(html);
body.add(HtmlTag.h1(TITLE));
HtmlTag meta = HtmlTag.stripedTable().appendTo(body);
meta.add(HtmlTag.tr().add(HtmlTag.td().add(HtmlTag.strong("Generated at:")), HtmlTag.td(new Date().toString())));
meta.add(HtmlTag.tr().add(HtmlTag.td().add(HtmlTag.strong("Weld Version:")), HtmlTag.td(Formats.getSimpleVersion())));
meta.add(HtmlTag.tr().add(HtmlTag.td().add(HtmlTag.strong("Weld Environment:")), HtmlTag.td(environment.toString())));
meta.add(HtmlTag.tr().add(HtmlTag.td().add(HtmlTag.strong("Java Version:")),
HtmlTag.td(AccessController.doPrivileged(new GetSystemPropertyAction("java.version")))));
meta.add(HtmlTag.tr().add(HtmlTag.td().add(HtmlTag.strong("Java Vendor:")),
HtmlTag.td(AccessController.doPrivileged(new GetSystemPropertyAction("java.vendor")))));
meta.add(HtmlTag.tr().add(HtmlTag.td().add(HtmlTag.strong("Operating System:")),
HtmlTag.td(AccessController.doPrivileged(new GetSystemPropertyAction("os.name")))));
HtmlTag contents = HtmlTag.ol().appendTo(body);
contents.add(HtmlTag.li().add(HtmlTag.a("#" + EXCEPTION).add(TITLE_EXCEPTION)));
contents.add(HtmlTag.li().add(HtmlTag.a("#" + BDAS).add(TITLE_BDAS)));
contents.add(HtmlTag.li().add(HtmlTag.a("#" + DEPS).add(TITLE_DEPS)));
contents.add(HtmlTag.li().add(HtmlTag.a("#" + BEANS).add(TITLE_BEANS)));
contents.add(HtmlTag.li().add(HtmlTag.a("#" + CONFIG).add(TITLE_CONFIG)));
body.add(HtmlTag.aname(EXCEPTION));
body.add(HtmlTag.h2(TITLE_EXCEPTION));
body.add(HtmlTag.p(exception.getMessage()).attr(HtmlTag.STYLE, "font-size: large;color: red;font-weight:bold;"));
body.add(HtmlTag.h(3, "Exception Stack:"));
final StringWriter stackWriter = new StringWriter();
exception.printStackTrace(new PrintWriter(stackWriter));
body.add(HtmlTag.div(EXCEPTION).add(HtmlTag.pre(stackWriter.toString())));
Map beanDeploymentArchivesMap = Container.instance(manager).beanDeploymentArchives();
List bdas = new ArrayList(beanDeploymentArchivesMap.keySet());
Collections.sort(bdas, probe.getBdaComparator());
addBeanArchives(body, bdas);
addInvalidDependencies(probe, body);
addBeans(probe, body, bdas);
addConfiguration(body, manager);
String export = manager.getServices().get(WeldConfiguration.class).getStringProperty(ConfigurationKey.PROBE_EXPORT_DATA_AFTER_DEPLOYMENT);
File exportPath;
if (!export.isEmpty()) {
exportPath = new File(export);
} else {
exportPath = new File(System.getProperty("user.dir"));
}
if (!exportPath.canWrite()) {
ProbeLogger.LOG.invalidExportPath(exportPath);
return;
}
try {
File exportFile = new File(exportPath, VALIDATION_REPORT_FILE_NAME);
Files.write(exportFile.toPath(), html.toString().getBytes(Charset.forName("UTF-8")));
ProbeLogger.LOG.validationReportExported("file://" + exportFile.getAbsolutePath());
} catch (IOException e) {
ProbeLogger.LOG.unableToExportData(exportPath, e.getCause() != null ? e.getCause() : e);
ProbeLogger.LOG.catchingTrace(e);
}
}
private static void addInvalidDependencies(Probe probe, HtmlTag body) {
body.add(HtmlTag.aname(DEPS));
body.add(HtmlTag.h2(TITLE_DEPS));
HtmlTag table = HtmlTag.stripedTable().appendTo(HtmlTag.div(DEPS).appendTo(body));
HtmlTag.tr().add(HtmlTag.th(""), HtmlTag.th("Declaring Bean"), HtmlTag.th("Problem")).appendTo(table);
int idx = 0;
for (Bean> bean : probe.getBeans()) {
final BeanManagerImpl beanManager = probe.getBeanManager(bean);
// Don't process built-in beans
if (beanManager == null) {
continue;
}
Set injectionPoints = bean.getInjectionPoints();
if (injectionPoints != null && !injectionPoints.isEmpty()) {
for (InjectionPoint injectionPoint : injectionPoints) {
if (injectionPoint.isDelegate()) {
// Do not process delegate injection points
continue;
}
Set> beans = beanManager.getBeans(injectionPoint.getType(),
injectionPoint.getQualifiers().toArray(new Annotation[injectionPoint.getQualifiers().size()]));
if (beans.isEmpty()) {
// Unsatisfied
HtmlTag.tr().add(HtmlTag.td(++idx + "."), HtmlTag.td(bean.toString()).add(HtmlTag.td("Unsatisfied dependency at " + injectionPoint)))
.appendTo(table);
try {
beanManager.resolve(beans);
} catch (AmbiguousResolutionException e) {
// Ambiguous
HtmlTag.tr().add(HtmlTag.td(++idx + "."), HtmlTag.td(bean.toString()).add(HtmlTag.td("Ambiguous dependency at " + injectionPoint)))
.appendTo(table);
}
}
}
}
}
}
private static void addBeanArchives(HtmlTag body, List bdas) {
body.add(HtmlTag.aname(BDAS));
body.add(HtmlTag.h2(TITLE_BDAS));
HtmlTag table = HtmlTag.stripedTable().appendTo(HtmlTag.div(BDAS).appendTo(body));
HtmlTag.tr().add(HtmlTag.th(""), HtmlTag.th("Identifier"), HtmlTag.th("Bean Discovery Mode"), HtmlTag.th("beans.xml")).appendTo(table);
int idx = 0;
for (BeanDeploymentArchive bda : bdas) {
HtmlTag tr = HtmlTag.tr().add(HtmlTag.td(++idx + "."), HtmlTag.td(bda.getId())).appendTo(table);
BeansXml beansXml = bda.getBeansXml();
tr.add(HtmlTag.td(beansXml != null ? beansXml.getBeanDiscoveryMode().toString() : BeanDiscoveryMode.ANNOTATED.toString()));
if (beansXml != null && !beansXml.equals(BeansXml.EMPTY_BEANS_XML)) {
HtmlTag.div().attr(HtmlTag.TITLE, beansXml.getUrl() != null ? beansXml.getUrl().toString() : "URL not available")
.add(beansXml.getVersion() != null ? beansXml.getVersion() : "Version not defined").appendTo(HtmlTag.td().appendTo(tr));
} else {
tr.add(HtmlTag.td("No beans.xml"));
}
}
}
private static void addConfiguration(HtmlTag body, BeanManagerImpl manager) {
body.add(HtmlTag.aname(CONFIG));
body.add(HtmlTag.h2(TITLE_CONFIG));
HtmlTag table = HtmlTag.stripedTable().appendTo(HtmlTag.div(CONFIG).appendTo(body));
HtmlTag.tr().add(HtmlTag.th(""), HtmlTag.th("Key"), HtmlTag.th("Default Value"), HtmlTag.th("Value"), HtmlTag.th("Description")).appendTo(table);
int idx = 0;
WeldConfiguration configuration = manager.getServices().get(WeldConfiguration.class);
for (ConfigurationKey key : getSortedConfigurationKeys()) {
Object defaultValue = key.getDefaultValue();
Object value = getValue(key, configuration);
if (value == null) {
// Unsupported property type
continue;
}
if (!defaultValue.equals(value)) {
String desc = getDesc(key);
table.add(HtmlTag.tr().add(HtmlTag.td(++idx + "."), HtmlTag.td(key.get()), HtmlTag.td(defaultValue.toString()), HtmlTag.td(value.toString()),
HtmlTag.td().add(desc != null ? SafeString.of(desc) : "")));
}
}
}
private static void addBeans(Probe probe, HtmlTag body, List bdas) {
body.add(HtmlTag.aname(BEANS));
body.add(HtmlTag.h2(TITLE_BEANS));
HtmlTag table = HtmlTag.stripedTable().appendTo(HtmlTag.div(BEANS).appendTo(body));
HtmlTag.tr().add(HtmlTag.th(""), HtmlTag.th("Archive"), HtmlTag.th("Kind"), HtmlTag.th("Bean Class"), HtmlTag.th("Types"), HtmlTag.th("Qualifiers"),
HtmlTag.th("Scope")).appendTo(table);
int idx = 0;
List> beans = probe.getBeans();
for (int i = 0; i < bdas.size(); i++) {
String bdaId = bdas.get(i).getId();
for (Bean> bean : beans) {
final BeanManagerImpl beanManager = probe.getBeanManager(bean);
// Don't process built-in beans
if (beanManager == null) {
continue;
}
if (bdaId.equals(beanManager.getId())) {
HtmlTag types = HtmlTag.td();
for (Iterator iterator = JsonObjects.sortTypes(bean.getTypes()).iterator(); iterator.hasNext();) {
// Omit java.lang.Object
Type type = iterator.next();
String formatted = Strings.escape(Formats.formatType(type, false));
if (!Object.class.equals(type)) {
types.add(HtmlTag.div().attr(HtmlTag.TITLE, formatted).add(abbreviateType(formatted)));
if (iterator.hasNext()) {
types.add(HtmlTag.BR);
}
}
}
HtmlTag qualifiers = HtmlTag.td();
if (bean.getQualifiers() != null && !bean.getQualifiers().isEmpty()) {
for (Iterator iterator = bean.getQualifiers().iterator(); iterator.hasNext();) {
Annotation qualifier = iterator.next();
if (Any.class.equals(qualifier.annotationType())) {
// Omit javax.enterprise.inject.Any
continue;
} else if (Default.class.equals(qualifier.annotationType())) {
qualifiers.add(JsonObjects.simplifiedAnnotation(qualifier));
} else {
qualifiers.add(HtmlTag.div().attr(HtmlTag.TITLE, qualifier.toString()).add(abbreviateAnnotation(qualifier.toString())));
}
if (iterator.hasNext()) {
qualifiers.add(HtmlTag.BR);
}
}
}
String beanClass = Formats.formatType(bean.getBeanClass(), false);
HtmlTag.tr()
.add(HtmlTag.td(++idx + "."), HtmlTag.td().add(HtmlTag.a("#" + BDAS).add(" " + (i + 1))),
HtmlTag.td(BeanKind.from(bean).toString()),
HtmlTag.td().add(HtmlTag.div().attr(HtmlTag.TITLE, beanClass).add(abbreviateType(beanClass))), types, qualifiers,
HtmlTag.td(JsonObjects.simplifiedScope(bean.getScope())))
.appendTo(table);
}
}
}
}
static List getSortedConfigurationKeys() {
List configurationKeys = new ArrayList<>();
Collections.addAll(configurationKeys, ConfigurationKey.values());
Collections.sort(configurationKeys, new Comparator() {
@Override
public int compare(ConfigurationKey o1, ConfigurationKey o2) {
return o1.get().compareTo(o2.get());
}
});
return configurationKeys;
}
static Object getValue(ConfigurationKey key, WeldConfiguration configuration) {
Object defaultValue = key.getDefaultValue();
Object value = null;
if (defaultValue instanceof Boolean) {
value = configuration.getBooleanProperty(key);
} else if (defaultValue instanceof Long) {
value = configuration.getLongProperty(key);
} else if (defaultValue instanceof Integer) {
value = configuration.getIntegerProperty(key);
} else if (defaultValue instanceof String) {
value = configuration.getStringProperty(key);
}
return value;
}
static String getDesc(ConfigurationKey key) {
try {
Field field = ConfigurationKey.class.getDeclaredField(key.toString());
if (field != null && field.isEnumConstant()) {
Description description = field.getAnnotation(Description.class);
if (description == null) {
// Don't show config options without description
return null;
}
return description.value();
}
} catch (NoSuchFieldException | SecurityException | NullPointerException ignored) {
}
return null;
}
private static String abbreviateType(String type) {
StringBuilder builder = new StringBuilder();
String[] parts = type.split("\\.");
for (int i = 0; i < parts.length; i++) {
if (i == (parts.length - 1)) {
builder.append(parts[i]);
} else {
builder.append(parts[i].charAt(0));
builder.append(".");
}
}
return builder.toString();
}
private static String abbreviateAnnotation(String annotation) {
if (annotation.indexOf('(') != -1) {
annotation = annotation.substring(1, annotation.indexOf('('));
} else {
annotation = annotation.substring(1);
}
return "@" + abbreviateType(annotation);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy