/* * JBoss, Home of Professional Open Source. * Copyright 2015, Red Hat, Inc., and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.as.test.integration.logging; import javax.inject.Inject; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLEncoder; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.jboss.as.controller.PathAddress; import org.jboss.as.controller.PathElement; import org.jboss.as.controller.client.Operation; import org.jboss.as.controller.client.helpers.Operations; import org.jboss.as.controller.client.helpers.standalone.ServerDeploymentHelper; import org.jboss.as.controller.client.helpers.standalone.ServerDeploymentHelper.ServerDeploymentException; import org.jboss.as.controller.descriptions.ModelDescriptionConstants; import org.jboss.as.test.shared.TestSuiteEnvironment; import org.jboss.dmr.ModelNode; import org.jboss.dmr.Property; import org.jboss.msc.service.ServiceActivator; import org.jboss.shrinkwrap.api.Archive; import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.asset.StringAsset; import org.jboss.shrinkwrap.api.exporter.ZipExporter; import org.jboss.shrinkwrap.api.spec.JavaArchive; import org.junit.Assert; import org.wildfly.core.testrunner.ManagementClient; /** * @author <a href="mailto:jperkins@redhat.com">James R. Perkins</a> */ public abstract class AbstractLoggingTestCase { public static final String DEPLOYMENT_NAME = "logging-test.jar"; public static final PathElement SUBSYSTEM_PATH = PathElement.pathElement(ModelDescriptionConstants.SUBSYSTEM, "logging"); public static final PathAddress SUBSYSTEM_ADDRESS = PathAddress.pathAddress(SUBSYSTEM_PATH); @Inject protected static ManagementClient client; public static JavaArchive createDeployment() { return createDeployment(LoggingServiceActivator.class, LoggingServiceActivator.DEPENDENCIES); } public static JavaArchive createDeployment(final Map<String, String> manifestEntries) { return createDeployment(LoggingServiceActivator.class, manifestEntries, LoggingServiceActivator.DEPENDENCIES); } public static JavaArchive createDeployment(final Class<? extends ServiceActivator> serviceActivator, final Class<?>... classes) { return createDeployment(serviceActivator, Collections.<String, String>emptyMap(), classes); } public static JavaArchive createDeployment(final Class<? extends ServiceActivator> serviceActivator, final Map<String, String> manifestEntries, final Class<?>... classes) { final JavaArchive archive = ShrinkWrap.create(JavaArchive.class, DEPLOYMENT_NAME); archive.addClasses(classes); archive.addAsServiceProviderAndClasses(ServiceActivator.class, serviceActivator); boolean addDeps = true; final StringBuilder manifest = new StringBuilder(); for (String key : manifestEntries.keySet()) { if ("Dependencies".equals(key)) { addDeps = false; manifest.append(key) .append(": ") .append("io.undertow.core,") .append(manifestEntries.get(key)) .append('\n'); } else { manifest.append(key) .append(": ") .append(manifestEntries.get(key)) .append('\n'); } } if (addDeps) { manifest.append("Dependencies: io.undertow.core"); } archive.addAsResource(new StringAsset(manifest.toString()), "META-INF/MANIFEST.MF"); return archive; } public static ModelNode executeOperation(final ModelNode op) throws IOException { ModelNode result = client.getControllerClient().execute(op); if (!Operations.isSuccessfulOutcome(result)) { Assert.assertTrue(Operations.getFailureDescription(result).toString(), false); } return result; } public static ModelNode executeOperation(final Operation op) throws IOException { ModelNode result = client.getControllerClient().execute(op); if (!Operations.isSuccessfulOutcome(result)) { Assert.assertTrue(Operations.getFailureDescription(result).toString(), false); } return result; } public static String resolveRelativePath(final String relativePath) { final ModelNode address = PathAddress.pathAddress( PathElement.pathElement(ModelDescriptionConstants.PATH, relativePath) ).toModelNode(); final ModelNode result; try { final ModelNode op = Operations.createReadAttributeOperation(address, ModelDescriptionConstants.PATH); result = client.getControllerClient().execute(op); if (Operations.isSuccessfulOutcome(result)) { return Operations.readResult(result).asString(); } } catch (IOException e) { throw new RuntimeException(e); } throw new RuntimeException(Operations.getFailureDescription(result).asString()); } public static Path getAbsoluteLogFilePath(final String filename) { return Paths.get(resolveRelativePath("jboss.server.log.dir"), filename); } public static void setEnabled(final ModelNode address, final boolean enabled) throws IOException { final ModelNode op = Operations.createWriteAttributeOperation(address, ModelDescriptionConstants.ENABLED, enabled); executeOperation(op); } /** * Deploys the archive to the running server. * * @param archive the archive to deploy * @param runtimeName the runtime name for the deployment * * @throws ServerDeploymentException if an error occurs deploying the archive */ public static void deploy(final Archive<?> archive, final String runtimeName) throws ServerDeploymentException { final ServerDeploymentHelper helper = new ServerDeploymentHelper(client.getControllerClient()); helper.deploy(runtimeName, archive.as(ZipExporter.class).exportAsInputStream()); } /** * Undeploys the application from the running server. * * @param runtimeNames the runtime names * * @throws ServerDeploymentException if an error occurs undeploying the application */ public static void undeploy(final String... runtimeNames) throws ServerDeploymentException { final ServerDeploymentHelper helper = new ServerDeploymentHelper(client.getControllerClient()); final Collection<Throwable> errors = new ArrayList<>(); for (String runtimeName : runtimeNames) { try { final ModelNode op = Operations.createReadResourceOperation(Operations.createAddress("deployment", runtimeName)); final ModelNode result = client.getControllerClient().execute(op); if (Operations.isSuccessfulOutcome(result)) helper.undeploy(runtimeName); } catch (Exception e) { errors.add(e); } } if (!errors.isEmpty()) { final RuntimeException e = new RuntimeException("Error undeploying: " + Arrays.asList(runtimeNames)); errors.forEach(e::addSuppressed); throw e; } } public static ModelNode createAddress(final String resourceKey, final String resourceName) { return PathAddress.pathAddress( SUBSYSTEM_PATH, PathElement.pathElement(resourceKey, resourceName) ).toModelNode(); } public static ModelNode createAddress(final String... paths) { PathAddress address = SUBSYSTEM_ADDRESS; for (int i = 0; i < paths.length; i++) { final String key = paths[i]; if (++i < paths.length) { address = address.append(PathElement.pathElement(key, paths[i])); } else { address = address.append(PathElement.pathElement(key)); } } return address.toModelNode(); } /** * Creates a new URL with the default context from {@link org.jboss.as.test.shared.TestSuiteEnvironment#getHttpUrl()} * and a query parameter of {@code msg} with a value of the argument. The argument will be encoded in UTF-8. * * @param msg the non-encoded message to send * @param params an optional list of extra parameters to add to the URL. * * @return a URL to send to the server * * @throws UnsupportedEncodingException if the UTF-8 encoding is not supported * @throws MalformedURLException if the URL is malformed */ public static URL createUrl(final String msg, final Map<String, String> params) throws UnsupportedEncodingException, MalformedURLException { final StringBuilder spec = new StringBuilder() .append('?') .append(LoggingServiceActivator.MSG_KEY) .append('=') .append(URLEncoder.encode(msg, "utf-8")); for (String key : params.keySet()) { spec.append('&').append(key); final String value = params.get(URLEncoder.encode(key, "utf-8")); if (value != null) { spec.append('=').append(URLEncoder.encode(value, "utf-8")); } } return new URL(TestSuiteEnvironment.getHttpUrl(), spec.toString()); } /** * {@link AbstractLoggingTestCase#createUrl(String, java.util.Map) Creates} a URL with the message provided and * opens a connection * to the sever returning the response code. * * @param msg the non-encoded message to send * * @return the response code from the server * * @throws IOException if there was an error creating the URL or connecting to he server * @see #createUrl(String, java.util.Map) * @see #getResponse(java.net.URL) */ public static int getResponse(final String msg) throws IOException { return getResponse(createUrl(msg, Collections.<String, String>emptyMap())); } /** * {@link AbstractLoggingTestCase#createUrl(String, java.util.Map) Creates} a URL with the message provided and * opens a connection * to the sever returning the response code. * * @param msg the non-encoded message to send * * @return the response code from the server * * @throws IOException if there was an error creating the URL or connecting to he server * @see #createUrl(String, java.util.Map) * @see #getResponse(java.net.URL) */ public static int getResponse(final String msg, final Map<String, String> params) throws IOException { return getResponse(createUrl(msg, params)); } /** * Opens a connection to the server and returns the response code. * * @param url the URL to connect to * * @return the response code from the server * * @throws IOException if an error occurs connecting to the server */ public static int getResponse(final URL url) throws IOException { return ((HttpURLConnection) url.openConnection()).getResponseCode(); } /** * Reads the deployment resource. * * @param deploymentName the name of the deployment * * @return the model for the deployment * * @throws IOException if an error occurs connecting to the server */ public static ModelNode readDeploymentResource(final String deploymentName) throws IOException { // Don't guess on the address, just parse it as it comes back final ModelNode address = Operations.createAddress("deployment", deploymentName, "subsystem", "logging", "configuration", "*"); final ModelNode op = Operations.createReadResourceOperation(address); op.get("include-runtime").set(true); final ModelNode result = executeOperation(op); // Get the resulting model final List<ModelNode> loggingConfigurations = Operations.readResult(result).asList(); Assert.assertEquals("There should only be one logging configuration defined", 1, loggingConfigurations.size()); final LinkedList<Property> resultAddress = new LinkedList<>(Operations.getOperationAddress(loggingConfigurations.get(0)).asPropertyList()); return readDeploymentResource(deploymentName, resultAddress.getLast().getValue().asString()); } /** * Reads the deployment resource. * * @param deploymentName the name of the deployment * @param configurationName the name of the configuration for the address * * @return the model for the deployment * * @throws IOException if an error occurs connecting to the server */ public static ModelNode readDeploymentResource(final String deploymentName, final String configurationName) throws IOException { ModelNode address = Operations.createAddress("deployment", deploymentName, "subsystem", "logging", "configuration", configurationName); ModelNode op = Operations.createReadResourceOperation(address, true); op.get("include-runtime").set(true); final ModelNode result = Operations.readResult(executeOperation(op)); // Add the address on the result as the tests might need it result.get(ModelDescriptionConstants.OP_ADDR).set(address); return result; } }