diff --git a/legacy/web/pom.xml b/legacy/web/pom.xml
index 6dc2d3f4e248..85f8f8bafc1f 100644
--- a/legacy/web/pom.xml
+++ b/legacy/web/pom.xml
@@ -52,6 +52,11 @@
wildfly-controller
+
+ org.wildfly
+ wildfly-undertow
+
+
org.jboss.logging
jboss-logging
diff --git a/legacy/web/src/main/java/org/jboss/as/web/WebDefinition.java b/legacy/web/src/main/java/org/jboss/as/web/WebDefinition.java
index b9c126581158..248378dc882f 100644
--- a/legacy/web/src/main/java/org/jboss/as/web/WebDefinition.java
+++ b/legacy/web/src/main/java/org/jboss/as/web/WebDefinition.java
@@ -29,6 +29,7 @@
import org.jboss.as.controller.client.helpers.MeasurementUnit;
import org.jboss.as.controller.descriptions.ModelDescriptionConstants;
import org.jboss.as.controller.registry.AttributeAccess;
+import org.jboss.as.controller.registry.ManagementResourceRegistration;
import org.jboss.dmr.ModelNode;
import org.jboss.dmr.ModelType;
@@ -71,5 +72,10 @@ private WebDefinition() {
setDeprecated(WebExtension.DEPRECATED_SINCE);
}
+ @Override
+ public void registerOperations(ManagementResourceRegistration resourceRegistration) {
+ super.registerOperations(resourceRegistration);
+ WebMigrateOperation.registerOperations(resourceRegistration, getResourceDescriptionResolver());
+ }
}
diff --git a/legacy/web/src/main/java/org/jboss/as/web/WebExtension.java b/legacy/web/src/main/java/org/jboss/as/web/WebExtension.java
index a785c190a532..59379d573ae8 100644
--- a/legacy/web/src/main/java/org/jboss/as/web/WebExtension.java
+++ b/legacy/web/src/main/java/org/jboss/as/web/WebExtension.java
@@ -31,11 +31,10 @@
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.WRITE_ATTRIBUTE_OPERATION;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
import java.util.Map;
-import java.util.Set;
+import org.jboss.as.controller.Extension;
import org.jboss.as.controller.ExtensionContext;
import org.jboss.as.controller.ModelVersion;
import org.jboss.as.controller.OperationFailedException;
@@ -46,7 +45,8 @@
import org.jboss.as.controller.access.management.SensitiveTargetAccessConstraintDefinition;
import org.jboss.as.controller.descriptions.DeprecatedResourceDescriptionResolver;
import org.jboss.as.controller.descriptions.StandardResourceDescriptionResolver;
-import org.jboss.as.controller.extension.AbstractLegacyExtension;
+import org.jboss.as.controller.extension.UnsupportedSubsystemDescribeHandler;
+import org.jboss.as.controller.operations.common.GenericSubsystemDescribeHandler;
import org.jboss.as.controller.parsing.ExtensionParsingContext;
import org.jboss.as.controller.registry.AliasEntry;
import org.jboss.as.controller.registry.ManagementResourceRegistration;
@@ -67,7 +67,7 @@
* @author Emanuel Muckenhuber
* @author Tomaz Cerar
*/
-public class WebExtension extends AbstractLegacyExtension {
+public class WebExtension implements Extension {
public static final String SUBSYSTEM_NAME = "web";
public static final PathElement SUBSYSTEM_PATH = PathElement.pathElement(SUBSYSTEM, SUBSYSTEM_NAME);
public static final PathElement VALVE_PATH = PathElement.pathElement(Constants.VALVE);
@@ -99,7 +99,6 @@ public class WebExtension extends AbstractLegacyExtension {
new SensitivityClassification(SUBSYSTEM_NAME, "web-valve", false, false, false));
public WebExtension() {
- super(extensionName, SUBSYSTEM_NAME);
}
static StandardResourceDescriptionResolver getResourceDescriptionResolver(final String keyPrefix) {
@@ -108,7 +107,7 @@ static StandardResourceDescriptionResolver getResourceDescriptionResolver(final
}
@Override
- protected Set initializeLegacyModel(ExtensionContext context) {
+ public void initialize(ExtensionContext context) {
final SubsystemRegistration subsystem = context.registerSubsystem(SUBSYSTEM_NAME, CURRENT_MODEL_VERSION);
final ManagementResourceRegistration registration = subsystem.registerSubsystemModel(WebDefinition.INSTANCE);
@@ -164,11 +163,13 @@ protected Set initializeLegacyModel(ExtensionCon
registerTransformers_2_x_0(subsystem, 0);
registerTransformers_2_x_0(subsystem, 1);
}
- return Collections.singleton(registration);
+
+ registration.registerOperationHandler(GenericSubsystemDescribeHandler.DEFINITION,
+ new UnsupportedSubsystemDescribeHandler(extensionName));
}
@Override
- protected void initializeLegacyParsers(ExtensionParsingContext context) {
+ public void initializeParsers(ExtensionParsingContext context) {
for (Namespace ns : Namespace.values()) {
if (ns.getUriString() != null) {
context.setSubsystemXmlMapping(SUBSYSTEM_NAME, ns.getUriString(), WebSubsystemParser.getInstance());
diff --git a/legacy/web/src/main/java/org/jboss/as/web/WebMigrateOperation.java b/legacy/web/src/main/java/org/jboss/as/web/WebMigrateOperation.java
new file mode 100644
index 000000000000..e660db101cd9
--- /dev/null
+++ b/legacy/web/src/main/java/org/jboss/as/web/WebMigrateOperation.java
@@ -0,0 +1,717 @@
+/*
+ * 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.web;
+
+import org.jboss.as.controller.CompositeOperationHandler;
+import org.jboss.as.controller.OperationContext;
+import org.jboss.as.controller.OperationFailedException;
+import org.jboss.as.controller.OperationStepHandler;
+import org.jboss.as.controller.PathAddress;
+import org.jboss.as.controller.PathElement;
+import org.jboss.as.controller.RunningMode;
+import org.jboss.as.controller.SimpleOperationDefinitionBuilder;
+import org.jboss.as.controller.access.management.SensitiveTargetAccessConstraintDefinition;
+import org.jboss.as.controller.descriptions.ResourceDescriptionResolver;
+import org.jboss.as.controller.operations.common.GenericSubsystemDescribeHandler;
+import org.jboss.as.controller.registry.ManagementResourceRegistration;
+import org.jboss.as.controller.registry.OperationEntry;
+import org.jboss.as.controller.registry.Resource;
+import org.jboss.as.domain.management.security.KeystoreAttributes;
+import org.jboss.dmr.ModelNode;
+import org.jboss.dmr.ModelType;
+import org.jboss.dmr.ValueExpression;
+import org.wildfly.extension.io.IOExtension;
+import org.wildfly.extension.undertow.Constants;
+import org.wildfly.extension.undertow.UndertowExtension;
+import org.wildfly.extension.undertow.logging.UndertowLogger;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import static org.jboss.as.controller.OperationContext.Stage.MODEL;
+import static org.jboss.as.controller.PathAddress.EMPTY_ADDRESS;
+import static org.jboss.as.controller.PathAddress.pathAddress;
+import static org.jboss.as.controller.PathElement.pathElement;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADD;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADDRESS;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.AUTHENTICATION;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.COMPOSITE;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.CORE_SERVICE;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.EXTENSION;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.MANAGEMENT;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.MODULE;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.PATH;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.PROTOCOL;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RELATIVE_TO;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RESULT;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SECURITY_REALM;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SERVER_IDENTITY;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SOCKET_BINDING;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SSL;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.STEPS;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUBSYSTEM;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.TRUSTSTORE;
+import static org.jboss.as.controller.operations.common.Util.createAddOperation;
+import static org.jboss.as.controller.operations.common.Util.createOperation;
+import static org.jboss.as.controller.operations.common.Util.createRemoveOperation;
+
+/**
+ * Operation to migrate from the legacy web subsystem to the new undertow subsystem.
+ *
+ * This operation must be performed when the server is in admin-only mode.
+ * Internally, the operation:
+ *
+ *
+ * - query the description of all the web subsystem by invoking the :describe operation.
+ * This returns a list of :add operations for each web resources.
+ * - :add the new org.widlfy.extension.undertow extension
+ * - for each web resources, transform the :add operations to add the
+ * corresponding resource to the new undertow subsystem.
+ * In this step, changes to the resources model are taken into account
+ * - :remove the messaging subsystem
+ *
+ *
+ * The companion :describe-migration
operation will return a list of all the actual operations that would be
+ * performed during the invocation of the :migrate
operation.
+ *
+ * Note that all new operation addresses are generated for standalone mode. If this is a domain mode server
+ * then the addresses are fixed after they have been generated
+ *
+ * @author Jeff Mesnil (c) 2015 Red Hat inc.
+ * @author Stuart Douglas
+ */
+
+public class WebMigrateOperation implements OperationStepHandler {
+
+ private static final String UNDERTOW_EXTENSION = "org.wildfly.extension.undertow";
+ private static final String IO_EXTENSION = "org.wildfly.extension.io";
+
+ private static final String REALM_NAME = "jbossweb-migration-security-realm";
+
+ private static final OperationStepHandler DESCRIBE_MIGRATION_INSTANCE = new WebMigrateOperation(true);
+ private static final OperationStepHandler MIGRATE_INSTANCE = new WebMigrateOperation(false);
+ public static final PathElement DEFAULT_SERVER_PATH = pathElement(Constants.SERVER, "default");
+
+ private final boolean describe;
+
+ private WebMigrateOperation(boolean describe) {
+
+ this.describe = describe;
+ }
+
+ static void registerOperations(ManagementResourceRegistration registry, ResourceDescriptionResolver resourceDescriptionResolver) {
+ registry.registerOperationHandler(new SimpleOperationDefinitionBuilder("migrate", resourceDescriptionResolver)
+ .setRuntimeOnly()
+ .setAccessConstraints(SensitiveTargetAccessConstraintDefinition.READ_WHOLE_CONFIG)
+ .build(),
+ WebMigrateOperation.MIGRATE_INSTANCE);
+ registry.registerOperationHandler(new SimpleOperationDefinitionBuilder("describe-migration", resourceDescriptionResolver)
+ .setReplyType(ModelType.LIST).setReplyValueType(ModelType.OBJECT)
+ .setRuntimeOnly()
+ .setAccessConstraints(SensitiveTargetAccessConstraintDefinition.READ_WHOLE_CONFIG)
+ .build(),
+ WebMigrateOperation.DESCRIBE_MIGRATION_INSTANCE);
+ }
+
+ @Override
+ public void execute(OperationContext context, ModelNode operation) throws OperationFailedException {
+ if (!describe && context.getRunningMode() != RunningMode.ADMIN_ONLY) {
+ throw UndertowLogger.ROOT_LOGGER.migrateOperationAllowedOnlyInAdminOnly();
+ }
+
+ // node containing the description (list of add operations) of the legacy subsystem
+ final ModelNode legacyModelAddOps = new ModelNode();
+ //we don't preserve order, instead we sort by address length
+ //TODO: is this ok in every case?
+ final Map migrationOperations = new TreeMap<>(new Comparator() {
+ @Override
+ public int compare(PathAddress o1, PathAddress o2) {
+ final int compare = Integer.compare(o1.size(), o2.size());
+ if (compare != 0) {
+ return compare;
+ }
+ return o1.toString().compareTo(o2.toString());
+ }
+ });
+
+ // invoke an OSH to describe the legacy messaging subsystem
+ describeLegacyWebResources(context, legacyModelAddOps);
+ // invoke an OSH to add the messaging-activemq extension
+ // FIXME: this does not work it the extension :add is added to the migrationOperations directly (https://issues.jboss.org/browse/WFCORE-323)
+ addExtension(context, migrationOperations, describe, UNDERTOW_EXTENSION);
+ addExtension(context, migrationOperations, describe, IO_EXTENSION);
+
+ context.addStep(new OperationStepHandler() {
+ @Override
+ public void execute(OperationContext context, ModelNode operation) throws OperationFailedException {
+ addDefaultResources(migrationOperations, legacyModelAddOps);
+
+ //create the new IO subsystem
+ createIoSubsystem(context, migrationOperations);
+
+ createWelcomeContentHandler(migrationOperations);
+
+ // transform the legacy add operations and put them in migrationOperations
+ transformResources(context, legacyModelAddOps, migrationOperations);
+
+ // put the /subsystem=messaging:remove operation
+ removeWebSubsystem(migrationOperations);
+
+ fixAddressesForDomainMode(pathAddress(operation.get(ADDRESS)), migrationOperations);
+
+ if (describe) {
+ // :describe-migration operation
+
+ // for describe-migration operation, do nothing and return the list of operations that would
+ // be executed in the composite operation
+ context.getResult().set(migrationOperations.values());
+ } else {
+ // :migrate operation
+ // invoke an OSH on a composite operation with all the migration operations
+ migrateSubsystems(context, migrationOperations);
+ }
+ }
+ }, MODEL);
+ }
+
+ /**
+ * Creates the security realm
+ *
+ * @param context
+ * @param migrationOperations
+ * @return
+ */
+ private SSLInformation createSecurityRealm(OperationContext context, Map migrationOperations, ModelNode legacyModelAddOps, String connector) {
+ ModelNode legacyAddOp = findResource(pathAddress(WebExtension.SUBSYSTEM_PATH, pathElement(WebExtension.CONNECTOR_PATH.getKey(), connector), pathElement("configuration", "ssl")), legacyModelAddOps);
+ if (legacyAddOp == null) {
+ return null;
+ }
+ //we have SSL
+ //now we need to find a unique name
+ //in domain mode different profiles could have different SSL configurations
+ //but the realms are not scoped to a profile
+ //if we hard coded a name migration would fail when migrating domains with multiple profiles
+ int counter = 1;
+ String realmName = REALM_NAME + counter;
+ boolean ok = false;
+ do {
+ Resource root = context.readResourceFromRoot(pathAddress(CORE_SERVICE, MANAGEMENT), false);
+ if (root.getChildrenNames(SECURITY_REALM).contains(realmName)) {
+ counter++;
+ realmName = REALM_NAME + counter;
+ } else {
+ ok = true;
+ }
+ } while (!ok);
+
+ //we have a unique realm name
+ //add the realm
+ PathAddress addres = pathAddress(pathElement(CORE_SERVICE, MANAGEMENT), pathElement(SECURITY_REALM, realmName));
+ migrationOperations.put(addres, createAddOperation(addres));
+
+ //read all the info from the SSL definition
+ ModelNode keyAlias = legacyAddOp.get(WebSSLDefinition.KEY_ALIAS.getName());
+ ModelNode password = legacyAddOp.get(WebSSLDefinition.PASSWORD.getName());
+ ModelNode certificateKeyFile = legacyAddOp.get(WebSSLDefinition.CERTIFICATE_KEY_FILE.getName());
+ ModelNode cipherSuite = legacyAddOp.get(WebSSLDefinition.CIPHER_SUITE.getName());
+ ModelNode protocol = legacyAddOp.get(WebSSLDefinition.PROTOCOL.getName());
+ ModelNode verifyClient = legacyAddOp.get(WebSSLDefinition.VERIFY_CLIENT.getName());
+ ModelNode verifyDepth = legacyAddOp.get(WebSSLDefinition.VERIFY_DEPTH.getName());
+ ModelNode certificateFile = legacyAddOp.get(WebSSLDefinition.CERTIFICATE_FILE.getName());
+ ModelNode caCertificateFile = legacyAddOp.get(WebSSLDefinition.CA_CERTIFICATE_FILE.getName());
+ ModelNode caCertificatePassword = legacyAddOp.get(WebSSLDefinition.CA_CERTIFICATE_PASSWORD.getName());
+ ModelNode csRevocationURL = legacyAddOp.get(WebSSLDefinition.CA_REVOCATION_URL.getName());
+ ModelNode trustStoreType = legacyAddOp.get(WebSSLDefinition.TRUSTSTORE_TYPE.getName());
+ ModelNode keystoreType = legacyAddOp.get(WebSSLDefinition.KEYSTORE_TYPE.getName());
+ ModelNode sessionCacheSize = legacyAddOp.get(WebSSLDefinition.SESSION_CACHE_SIZE.getName());
+ ModelNode sessionTimeout = legacyAddOp.get(WebSSLDefinition.SESSION_TIMEOUT.getName());
+ ModelNode sslProtocol = legacyAddOp.get(WebSSLDefinition.SSL_PROTOCOL.getName());
+
+ //now lets add the trust store
+ addres = pathAddress(pathElement(CORE_SERVICE, MANAGEMENT), pathElement(SECURITY_REALM, realmName), pathElement(AUTHENTICATION, TRUSTSTORE));
+ ModelNode addOp = createAddOperation(addres);
+ addOp.get(KeystoreAttributes.KEYSTORE_PATH.getName()).set(caCertificateFile);
+ addOp.get(KeystoreAttributes.KEYSTORE_PASSWORD.getName()).set(caCertificatePassword);
+ addOp.get(KeystoreAttributes.KEYSTORE_PROVIDER.getName()).set(trustStoreType);
+ migrationOperations.put(addres, addOp);
+
+
+ //now lets add the key store
+ addres = pathAddress(pathElement(CORE_SERVICE, MANAGEMENT), pathElement(SECURITY_REALM, realmName), pathElement(SERVER_IDENTITY, SSL));
+ addOp = createAddOperation(addres);
+ addOp.get(KeystoreAttributes.KEYSTORE_PATH.getName()).set(certificateKeyFile);
+ addOp.get(KeystoreAttributes.KEYSTORE_PASSWORD.getName()).set(password);
+ addOp.get(KeystoreAttributes.KEYSTORE_PROVIDER.getName()).set(keystoreType);
+ addOp.get(KeystoreAttributes.ALIAS.getName()).set(keyAlias);
+ addOp.get(PROTOCOL).set(protocol);
+ //addOp.get(KeystoreAttributes.KEY_PASSWORD.getName()).set(password); //TODO: is this correct? both key and keystore have same password?
+
+ if(verifyDepth.isDefined()) {
+ UndertowLogger.ROOT_LOGGER.couldNotMigrateResource(WebSSLDefinition.VERIFY_DEPTH.getName(), pathAddress(legacyAddOp.get(ADDRESS)));
+ }
+ if(certificateFile.isDefined()) {
+ UndertowLogger.ROOT_LOGGER.couldNotMigrateResource(WebSSLDefinition.CERTIFICATE_FILE.getName(), pathAddress(legacyAddOp.get(ADDRESS)));
+ }
+
+ if(csRevocationURL.isDefined()) {
+ UndertowLogger.ROOT_LOGGER.couldNotMigrateResource(WebSSLDefinition.CA_REVOCATION_URL.getName(), pathAddress(legacyAddOp.get(ADDRESS)));
+ }
+
+ migrationOperations.put(addres, addOp);
+
+ return new SSLInformation(realmName, verifyClient, sessionCacheSize, sessionTimeout, sslProtocol, cipherSuite);
+ }
+
+ private void fixAddressesForDomainMode(PathAddress migrateAddress, Map migrationOperations) {
+ int i = 0;
+ while (i < migrateAddress.size()) {
+ if (migrateAddress.getElement(i).equals(WebExtension.SUBSYSTEM_PATH)) {
+ break;
+ }
+ ++i;
+ }
+ if (i == 0) {
+ //not domain mode, no need for a prefix
+ return;
+ }
+ PathAddress prefix = migrateAddress.subAddress(0, i);
+ Map old = new HashMap<>(migrationOperations);
+ migrationOperations.clear();
+ for (Map.Entry e : old.entrySet()) {
+ if (e.getKey().getElement(0).getKey().equals(SUBSYSTEM)) {
+ final PathAddress oldAddress = pathAddress(e.getValue().get(ADDRESS));
+ List elements = new ArrayList<>();
+ for (PathElement j : prefix) {
+ elements.add(j);
+ }
+ for (PathElement j : oldAddress) {
+ elements.add(j);
+ }
+ PathAddress newAddress = pathAddress(elements);
+ e.getValue().get(ADDRESS).set(newAddress.toModelNode());
+ migrationOperations.put(newAddress, e.getValue());
+ } else {
+ //not targeted at a subsystem
+ migrationOperations.put(e.getKey(), e.getValue());
+ }
+ }
+ }
+
+ /**
+ * We need to create the IO subsystem, if it does not already exist
+ */
+ private void createIoSubsystem(OperationContext context, Map migrationOperations) {
+ Resource root = context.readResourceFromRoot(PathAddress.EMPTY_ADDRESS, false);
+ if (root.getChildrenNames(SUBSYSTEM).contains(IOExtension.SUBSYSTEM_NAME)) {
+ // subsystem is already added, do nothing
+ return;
+ }
+
+ PathAddress address = pathAddress(pathElement(SUBSYSTEM, IOExtension.SUBSYSTEM_NAME));
+ migrationOperations.put(address, createAddOperation(address));
+ address = pathAddress(pathElement(SUBSYSTEM, IOExtension.SUBSYSTEM_NAME), pathElement("worker", "default"));
+ migrationOperations.put(address, createAddOperation(address));
+ address = pathAddress(pathElement(SUBSYSTEM, IOExtension.SUBSYSTEM_NAME), pathElement("buffer-pool", "default"));
+ migrationOperations.put(address, createAddOperation(address));
+
+ }
+
+
+ /**
+ * create a handler for serving welcome content
+ */
+ private void createWelcomeContentHandler(Map migrationOperations) {
+
+ PathAddress address = pathAddress(pathElement(SUBSYSTEM, UndertowExtension.SUBSYSTEM_NAME), pathElement(Constants.CONFIGURATION, Constants.HANDLER));
+ migrationOperations.put(address, createAddOperation(address));
+
+ address = pathAddress(pathElement(SUBSYSTEM, UndertowExtension.SUBSYSTEM_NAME), pathElement(Constants.CONFIGURATION, Constants.HANDLER), pathElement(Constants.FILE, "welcome-content"));
+ final ModelNode add = createAddOperation(address);
+ add.get(Constants.PATH).set(new ModelNode(new ValueExpression("${jboss.home.dir}/welcome-content")));
+ migrationOperations.put(address, add);
+ }
+
+ private void addDefaultResources(Map migrationOperations, final ModelNode legacyModelDescription) {
+ //add the default server
+ PathAddress address = pathAddress(pathElement(SUBSYSTEM, UndertowExtension.SUBSYSTEM_NAME), DEFAULT_SERVER_PATH);
+ ModelNode add = createAddOperation(address);
+
+ ModelNode defaultSessionTimeout = null;
+
+ //static resources
+ ModelNode directoryListing = null;
+ //todo: add support for some of these
+ ModelNode sendfile = null;
+ ModelNode fileEncoding = null;
+ ModelNode readOnly = null;
+ ModelNode webdav = null;
+ ModelNode secret = null;
+ ModelNode maxDepth = null;
+ ModelNode disabled = null;
+
+ for (ModelNode legacyAddOp : legacyModelDescription.get(RESULT).asList()) {
+ final PathAddress la = pathAddress(legacyAddOp.get(ADDRESS));
+ if (la.equals(pathAddress(WebExtension.SUBSYSTEM_PATH))) {
+ ModelNode defaultHost = legacyAddOp.get(WebDefinition.DEFAULT_VIRTUAL_SERVER.getName());
+ if (defaultHost.isDefined()) {
+ add.get(Constants.DEFAULT_HOST).set(defaultHost.clone());
+ }
+ ModelNode sessionTimeout = legacyAddOp.get(WebDefinition.DEFAULT_SESSION_TIMEOUT.getName());
+ if (sessionTimeout.isDefined()) {
+ defaultSessionTimeout = sessionTimeout;
+ }
+ } else if (la.equals(pathAddress(WebExtension.SUBSYSTEM_PATH, WebExtension.STATIC_RESOURCES_PATH))) {
+ ModelNode node = legacyAddOp.get(WebStaticResources.LISTINGS.getName());
+ if (node.isDefined()) {
+ directoryListing = node;
+ }
+ node = legacyAddOp.get(WebStaticResources.SENDFILE.getName());
+ if (node.isDefined()) {
+ UndertowLogger.ROOT_LOGGER.couldNotMigrateResource(WebStaticResources.SENDFILE.getName(), pathAddress(legacyAddOp.get(ADDRESS)));
+ sendfile = node;
+ }
+ node = legacyAddOp.get(WebStaticResources.FILE_ENCODING.getName());
+ if (node.isDefined()) {
+ UndertowLogger.ROOT_LOGGER.couldNotMigrateResource(WebStaticResources.FILE_ENCODING.getName(), pathAddress(legacyAddOp.get(ADDRESS)));
+ fileEncoding = node;
+ }
+ node = legacyAddOp.get(WebStaticResources.READ_ONLY.getName());
+ if (node.isDefined()) {
+ UndertowLogger.ROOT_LOGGER.couldNotMigrateResource(WebStaticResources.READ_ONLY.getName(), pathAddress(legacyAddOp.get(ADDRESS)));
+ readOnly = node;
+ }
+ node = legacyAddOp.get(WebStaticResources.WEBDAV.getName());
+ if (node.isDefined()) {
+ UndertowLogger.ROOT_LOGGER.couldNotMigrateResource(WebStaticResources.WEBDAV.getName(), pathAddress(legacyAddOp.get(ADDRESS)));
+ webdav = node;
+ }
+ node = legacyAddOp.get(WebStaticResources.SECRET.getName());
+ if (node.isDefined()) {
+ UndertowLogger.ROOT_LOGGER.couldNotMigrateResource(WebStaticResources.SECRET.getName(), pathAddress(legacyAddOp.get(ADDRESS)));
+ secret = node;
+ }
+ node = legacyAddOp.get(WebStaticResources.MAX_DEPTH.getName());
+ if (node.isDefined()) {
+ UndertowLogger.ROOT_LOGGER.couldNotMigrateResource(WebStaticResources.MAX_DEPTH.getName(), pathAddress(legacyAddOp.get(ADDRESS)));
+ maxDepth = node;
+ }
+ node = legacyAddOp.get(WebStaticResources.DISABLED.getName());
+ if (node.isDefined()) {
+ UndertowLogger.ROOT_LOGGER.couldNotMigrateResource(WebStaticResources.DISABLED.getName(), pathAddress(legacyAddOp.get(ADDRESS)));
+ disabled = node;
+ }
+ }
+ }
+
+ migrationOperations.put(address, add);
+ address = pathAddress(pathElement(SUBSYSTEM, UndertowExtension.SUBSYSTEM_NAME), pathElement(Constants.SERVLET_CONTAINER, "default"));
+ add = createAddOperation(address);
+ if (defaultSessionTimeout != null) {
+ add.get(Constants.DEFAULT_SESSION_TIMEOUT).set(defaultSessionTimeout.clone());
+ }
+ if (directoryListing != null) {
+ add.get(Constants.DIRECTORY_LISTING).set(directoryListing);
+ }
+
+ migrationOperations.put(address, add);
+ }
+
+ /**
+ * It's possible that the extension is already present. In that case, this method does nothing.
+ */
+ private void addExtension(OperationContext context, Map migrationOperations, boolean describe, String extension) {
+ Resource root = context.readResourceFromRoot(PathAddress.EMPTY_ADDRESS, false);
+ if (root.getChildrenNames(EXTENSION).contains(extension)) {
+ // extension is already added, do nothing
+ return;
+ }
+ PathAddress extensionAddress = pathAddress(EXTENSION, extension);
+ OperationEntry addEntry = context.getRootResourceRegistration().getOperationEntry(extensionAddress, ADD);
+ ModelNode addOperation = createAddOperation(extensionAddress);
+ addOperation.get(MODULE).set(extension);
+ if (describe) {
+ migrationOperations.put(extensionAddress, addOperation);
+ } else {
+ context.addStep(context.getResult().get(extensionAddress.toString()), addOperation, addEntry.getOperationHandler(), MODEL);
+ }
+ }
+
+ private void removeWebSubsystem(Map migrationOperations) {
+ PathAddress subsystemAddress = pathAddress(WebExtension.SUBSYSTEM_PATH);
+ ModelNode removeOperation = createRemoveOperation(subsystemAddress);
+ migrationOperations.put(subsystemAddress, removeOperation);
+ }
+
+ private void migrateSubsystems(OperationContext context, final Map migrationOperations) {
+ ModelNode compositeOp = createOperation(COMPOSITE, EMPTY_ADDRESS);
+ compositeOp.get(STEPS).set(migrationOperations.values());
+ context.addStep(compositeOp, CompositeOperationHandler.INSTANCE, MODEL);
+ }
+
+ private void transformResources(final OperationContext context, final ModelNode legacyModelDescription, final Map newAddOperations) throws OperationFailedException {
+ for (ModelNode legacyAddOp : legacyModelDescription.get(RESULT).asList()) {
+ final ModelNode newAddOp = legacyAddOp.clone();
+ PathAddress address = pathAddress(newAddOp.get(ADDRESS));
+
+ if (address.size() == 1) {
+ //subsystem
+ migrateSubsystem(newAddOperations, newAddOp);
+ } else if (address.equals(pathAddress(WebExtension.SUBSYSTEM_PATH, WebExtension.STATIC_RESOURCES_PATH))) {
+ //covered in the servlet container add, so just ignore
+ } else if (address.equals(pathAddress(WebExtension.SUBSYSTEM_PATH, WebExtension.JSP_CONFIGURATION_PATH))) {
+ migrateJSPConfig(newAddOperations, newAddOp);
+ } else if (address.equals(pathAddress(WebExtension.SUBSYSTEM_PATH, WebExtension.CONTAINER_PATH))) {
+ migrateMimeMapping(newAddOperations, newAddOp);
+ } else if (wildcardEquals(address, pathAddress(WebExtension.SUBSYSTEM_PATH, WebExtension.CONNECTOR_PATH))) {
+ migrateConnector(context, newAddOperations, newAddOp, address, legacyModelDescription);
+ } else if (wildcardEquals(address, pathAddress(WebExtension.SUBSYSTEM_PATH, WebExtension.HOST_PATH))) {
+ migrateVirtualHost(newAddOperations, newAddOp, address);
+ } else if (wildcardEquals(address, pathAddress(WebExtension.SUBSYSTEM_PATH, WebExtension.HOST_PATH, WebExtension.ACCESS_LOG_PATH))) {
+ migrateAccessLog(newAddOperations, newAddOp, address, legacyModelDescription);
+ } else if (wildcardEquals(address, pathAddress(WebExtension.SUBSYSTEM_PATH, WebExtension.HOST_PATH, WebExtension.ACCESS_LOG_PATH, WebExtension.DIRECTORY_PATH))) {
+ //ignore, handled by access-log
+ } else if (wildcardEquals(address, pathAddress(WebExtension.SUBSYSTEM_PATH, WebExtension.HOST_PATH, WebExtension.SSO_PATH))) {
+ migrateSso(newAddOperations, newAddOp, address);
+ } else {
+ UndertowLogger.ROOT_LOGGER.couldNotMigrateResource(legacyAddOp);
+ }
+
+ }
+ }
+
+ private void migrateSso(Map newAddOperations, ModelNode newAddOp, PathAddress address) {
+ PathAddress newAddress = pathAddress(UndertowExtension.SUBSYSTEM_PATH, DEFAULT_SERVER_PATH, pathElement(Constants.HOST, address.getElement(address.size() - 2).getValue()), UndertowExtension.PATH_SSO);
+ ModelNode add = createAddOperation(newAddress);
+
+ add.get(Constants.DOMAIN).set(newAddOp.get(WebSSODefinition.DOMAIN.getName()).clone());
+ add.get(Constants.HTTP_ONLY).set(newAddOp.get(WebSSODefinition.HTTP_ONLY.getName()).clone());
+
+ if (newAddOp.hasDefined(WebSSODefinition.CACHE_CONTAINER.getName())) {
+ UndertowLogger.ROOT_LOGGER.couldNotMigrateResource(WebSSODefinition.CACHE_CONTAINER.getName(), pathAddress(newAddOp.get(ADDRESS)));
+ }
+ if (newAddOp.hasDefined(WebSSODefinition.REAUTHENTICATE.getName())) {
+ UndertowLogger.ROOT_LOGGER.couldNotMigrateResource(WebSSODefinition.REAUTHENTICATE.getName(), pathAddress(newAddOp.get(ADDRESS)));
+ }
+ if (newAddOp.hasDefined(WebSSODefinition.CACHE_NAME.getName())) {
+ UndertowLogger.ROOT_LOGGER.couldNotMigrateResource(WebSSODefinition.CACHE_NAME.getName(), pathAddress(newAddOp.get(ADDRESS)));
+ }
+
+ newAddOperations.put(newAddress, add);
+ }
+
+ private void migrateAccessLog(Map newAddOperations, ModelNode newAddOp, PathAddress address, ModelNode legacyAddOps) {
+ PathAddress newAddress = pathAddress(UndertowExtension.SUBSYSTEM_PATH, DEFAULT_SERVER_PATH, pathElement(Constants.HOST, address.getElement(address.size() - 2).getValue()), UndertowExtension.PATH_ACCESS_LOG);
+ ModelNode add = createAddOperation(newAddress);
+
+ //TODO: parse the pattern and modify to Undertow version
+ add.get(Constants.PATTERN).set(newAddOp.get(WebAccessLogDefinition.PATTERN.getName()).clone());
+ add.get(Constants.PREFIX).set(newAddOp.get(WebAccessLogDefinition.PREFIX.getName()).clone());
+ add.get(Constants.ROTATE).set(newAddOp.get(WebAccessLogDefinition.ROTATE.getName()).clone());
+ if (newAddOp.hasDefined(WebAccessLogDefinition.RESOLVE_HOSTS.getName())) {
+ UndertowLogger.ROOT_LOGGER.couldNotMigrateResource(WebAccessLogDefinition.RESOLVE_HOSTS.getName(), pathAddress(newAddOp.get(ADDRESS)));
+ }
+ //TODO: extended access log
+ if (newAddOp.hasDefined(WebAccessLogDefinition.EXTENDED.getName())) {
+ UndertowLogger.ROOT_LOGGER.couldNotMigrateResource(WebAccessLogDefinition.EXTENDED.getName(), pathAddress(newAddOp.get(ADDRESS)));
+ }
+
+ ModelNode directory = findResource(pathAddress(pathAddress(newAddOp.get(ADDRESS)), WebExtension.DIRECTORY_PATH), legacyAddOps);
+ if(directory != null){
+ newAddOp.get(Constants.DIRECTORY).set(directory.get(PATH));
+ newAddOp.get(Constants.RELATIVE_TO).set(directory.get(RELATIVE_TO));
+ }
+
+ newAddOperations.put(newAddress, add);
+ }
+
+ private boolean wildcardEquals(PathAddress a1, PathAddress a2) {
+ if (a1.size() != a2.size()) {
+ return false;
+ }
+ for (int i = 0; i < a1.size(); ++i) {
+ PathElement p1 = a1.getElement(i);
+ PathElement p2 = a2.getElement(i);
+ if (!p1.getKey().equals(p2.getKey())) {
+ return false;
+ }
+ if (!p1.isWildcard() && !p2.isWildcard()) {
+ if (!p1.getValue().equals(p2.getValue())) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private void migrateVirtualHost(Map newAddOperations, ModelNode newAddOp, PathAddress address) {
+ PathAddress newAddress = pathAddress(UndertowExtension.SUBSYSTEM_PATH, DEFAULT_SERVER_PATH, pathElement(Constants.HOST, address.getLastElement().getValue()));
+ ModelNode add = createAddOperation(newAddress);
+
+ if (newAddOp.hasDefined(WebVirtualHostDefinition.ENABLE_WELCOME_ROOT.getName()) && newAddOp.get(WebVirtualHostDefinition.ENABLE_WELCOME_ROOT.getName()).asBoolean()) {
+ PathAddress welcomeAddress = pathAddress(newAddress, pathElement(Constants.LOCATION, "/"));
+ ModelNode welcomeAdd = createAddOperation(welcomeAddress);
+ welcomeAdd.get(Constants.HANDLER).set("welcome-content");
+ newAddOperations.put(welcomeAddress, welcomeAdd);
+ }
+ add.get(Constants.ALIAS).set(newAddOp.get(WebVirtualHostDefinition.ALIAS.getName()).clone());
+ add.get(Constants.DEFAULT_WEB_MODULE).set(newAddOp.get(WebVirtualHostDefinition.DEFAULT_WEB_MODULE.getName()));
+
+ newAddOperations.put(newAddress, add);
+ }
+
+ private void migrateConnector(OperationContext context, Map newAddOperations, ModelNode newAddOp, PathAddress address, ModelNode legacyModelAddOps) throws OperationFailedException {
+ String protocol = newAddOp.get(WebConnectorDefinition.PROTOCOL.getName()).asString();
+ String scheme = null;
+ if (newAddOp.hasDefined(WebConnectorDefinition.SCHEME.getName())) {
+ scheme = newAddOp.get(WebConnectorDefinition.SCHEME.getName()).asString();
+ }
+ final PathAddress newAddress;
+ final ModelNode addConnector;
+ switch (protocol) {
+ case "HTTP/1.1":
+ if (scheme == null || scheme.equals("http")) {
+ newAddress = pathAddress(UndertowExtension.SUBSYSTEM_PATH, DEFAULT_SERVER_PATH, pathElement(Constants.HTTP_LISTENER, address.getLastElement().getValue()));
+ addConnector = createAddOperation(newAddress);
+ } else if (scheme.equals("https")) {
+ newAddress = pathAddress(UndertowExtension.SUBSYSTEM_PATH, DEFAULT_SERVER_PATH, pathElement(Constants.HTTPS_LISTENER, address.getLastElement().getValue()));
+ addConnector = createAddOperation(newAddress);
+
+ SSLInformation sslInfo = createSecurityRealm(context, newAddOperations, legacyModelAddOps, newAddress.getLastElement().getValue());
+ if (sslInfo == null) {
+ throw UndertowLogger.ROOT_LOGGER.noSslConfig();
+ } else {
+ addConnector.get(Constants.SECURITY_REALM).set(sslInfo.realmName);
+ addConnector.get(Constants.VERIFY_CLIENT).set(sslInfo.verifyClient);
+ addConnector.get(Constants.SSL_SESSION_CACHE_SIZE).set(sslInfo.sessionCacheSize);
+ addConnector.get(Constants.SSL_SESSION_TIMEOUT).set(sslInfo.sessionTimeout);
+ addConnector.get(Constants.ENABLED_PROTOCOLS).set(sslInfo.sslProtocol);
+ addConnector.get(Constants.ENABLED_CIPHER_SUITES).set(sslInfo.cipherSuites);
+ }
+ } else {
+ newAddress = null;
+ addConnector = null;
+ }
+ break;
+ case "AJP":
+ newAddress = pathAddress(UndertowExtension.SUBSYSTEM_PATH, DEFAULT_SERVER_PATH, pathElement(Constants.AJP_LISTENER, address.getLastElement().getValue()));
+ addConnector = createAddOperation(newAddress);
+ break;
+ default:
+ newAddress = null;
+ addConnector = null;
+ }
+ if (newAddress == null) {
+ UndertowLogger.ROOT_LOGGER.couldNotMigrateResource(newAddOp);
+ return;
+ }
+ addConnector.get(Constants.SOCKET_BINDING).set(newAddOp.get(SOCKET_BINDING));
+ addConnector.get(Constants.SECURE).set(newAddOp.get(WebConnectorDefinition.SECURE.getName()));
+ addConnector.get(Constants.REDIRECT_SOCKET).set(newAddOp.get(WebConnectorDefinition.REDIRECT_BINDING.getName()));
+ addConnector.get(Constants.ENABLED).set(newAddOp.get(WebConnectorDefinition.ENABLED.getName()));
+ addConnector.get(Constants.RESOLVE_PEER_ADDRESS).set(newAddOp.get(WebConnectorDefinition.ENABLE_LOOKUPS.getName()));
+ addConnector.get(Constants.MAX_POST_SIZE).set(newAddOp.get(WebConnectorDefinition.MAX_POST_SIZE.getName()));
+ addConnector.get(Constants.REDIRECT_SOCKET).set(newAddOp.get(WebConnectorDefinition.REDIRECT_BINDING.getName()));
+ //TODO: secure
+ //TODO: max save post size
+ //TODO: proxy binding
+ if (newAddOp.hasDefined(WebConnectorDefinition.EXECUTOR.getName())) {
+ //TODO: migrate executor to worker
+ UndertowLogger.ROOT_LOGGER.couldNotMigrateResource(WebConnectorDefinition.EXECUTOR.getName(), pathAddress(newAddOp.get(ADDRESS)));
+ }
+ //TODO: expose max connections
+ newAddOperations.put(pathAddress(newAddOp.get(OP_ADDR)), addConnector);
+ }
+
+ private void migrateMimeMapping(Map newAddOperations, ModelNode newAddOp) {
+ migrateWelcomeFiles(newAddOperations, newAddOp);
+ ModelNode mime = newAddOp.get("mime-mapping");
+ if (mime.isDefined()) {
+ for (ModelNode w : mime.asList()) {
+ PathAddress wa = pathAddress(pathAddress(UndertowExtension.SUBSYSTEM_PATH, pathElement(Constants.SERVLET_CONTAINER, "default"), pathElement(Constants.MIME_MAPPING, w.asProperty().getName())));
+ ModelNode add = createAddOperation(wa);
+ add.get(Constants.VALUE).set(w.asProperty().getValue());
+ newAddOperations.put(wa, add);
+
+ }
+ }
+ }
+
+ private void migrateWelcomeFiles(Map newAddOperations, ModelNode newAddOp) {
+ ModelNode welcome = newAddOp.get("welcome-file");
+ if (welcome.isDefined()) {
+ for (ModelNode w : welcome.asList()) {
+ PathAddress wa = pathAddress(pathAddress(UndertowExtension.SUBSYSTEM_PATH, pathElement(Constants.SERVLET_CONTAINER, "default"), pathElement(Constants.WELCOME_FILE, w.asString())));
+ ModelNode add = createAddOperation(wa);
+ newAddOperations.put(wa, add);
+ }
+ }
+ }
+
+ private void migrateJSPConfig(Map newAddOperations, ModelNode newAddOp) {
+ newAddOp.get(ADDRESS).set(pathAddress(UndertowExtension.SUBSYSTEM_PATH, pathElement(Constants.SERVLET_CONTAINER, "default"), UndertowExtension.PATH_JSP).toModelNode());
+ newAddOperations.put(pathAddress(newAddOp.get(OP_ADDR)), newAddOp);
+ }
+
+ private void migrateSubsystem(Map newAddOperations, ModelNode newAddOp) {
+ newAddOp.get(ADDRESS).set(pathAddress(pathElement(SUBSYSTEM, UndertowExtension.SUBSYSTEM_NAME)).toModelNode());
+ newAddOperations.put(pathAddress(newAddOp.get(OP_ADDR)), newAddOp);
+ }
+
+ private void describeLegacyWebResources(OperationContext context, ModelNode legacyModelDescription) {
+ ModelNode describeLegacySubsystem = createOperation(GenericSubsystemDescribeHandler.DEFINITION, context.getCurrentAddress());
+ context.addStep(legacyModelDescription, describeLegacySubsystem, GenericSubsystemDescribeHandler.INSTANCE, MODEL, true);
+ }
+
+ private static ModelNode findResource(PathAddress address, ModelNode legacyAddOps) {
+ for (ModelNode legacyAddOp : legacyAddOps.get(RESULT).asList()) {
+ final PathAddress la = pathAddress(legacyAddOp.get(ADDRESS));
+ if (la.equals(address)) {
+ return legacyAddOp;
+ }
+ }
+ return null;
+ }
+
+ private class SSLInformation {
+ final String realmName;
+ final ModelNode verifyClient;
+ final ModelNode sessionCacheSize;
+ final ModelNode sessionTimeout;
+ final ModelNode sslProtocol;
+ final ModelNode cipherSuites;
+
+ private SSLInformation(String realmName, ModelNode verifyClient, ModelNode sessionCacheSize, ModelNode sessionTimeout, ModelNode sslProtocol, ModelNode cipherSuites) {
+ this.realmName = realmName;
+ this.verifyClient = verifyClient;
+ this.sessionCacheSize = sessionCacheSize;
+ this.sessionTimeout = sessionTimeout;
+ this.sslProtocol = sslProtocol;
+ this.cipherSuites = cipherSuites;
+ }
+ }
+}
diff --git a/legacy/web/src/main/resources/org/jboss/as/web/LocalDescriptions.properties b/legacy/web/src/main/resources/org/jboss/as/web/LocalDescriptions.properties
index 93e0b21b0b1d..ecfe1bf0d97e 100644
--- a/legacy/web/src/main/resources/org/jboss/as/web/LocalDescriptions.properties
+++ b/legacy/web/src/main/resources/org/jboss/as/web/LocalDescriptions.properties
@@ -6,6 +6,8 @@ web.instance-id=Set the identifier for this server instance.
web.native=Add the native initialization listener to the web container.
web.remove=Operation removing the web subsystem.
web.deprecated=The Web subsystem is deprecated and may be removed or limited to managed domain legacy server use in future versions.
+web.describe-migration=Describes the steps that will be taken to migrate this configuration to Undertow
+web.migrate=Migrates this web subsystem config to Undertow
web.container=Common container configuration
web.container.add=Adds web container
diff --git a/legacy/web/src/test/java/org/jboss/as/web/test/WebMigrateTestCase.java b/legacy/web/src/test/java/org/jboss/as/web/test/WebMigrateTestCase.java
new file mode 100644
index 000000000000..c2d318466358
--- /dev/null
+++ b/legacy/web/src/test/java/org/jboss/as/web/test/WebMigrateTestCase.java
@@ -0,0 +1,227 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2015, Red Hat Middleware LLC, 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.web.test;
+
+import org.jboss.as.controller.OperationContext;
+import org.jboss.as.controller.OperationFailedException;
+import org.jboss.as.controller.OperationStepHandler;
+import org.jboss.as.controller.PathElement;
+import org.jboss.as.controller.RunningMode;
+import org.jboss.as.controller.SimpleResourceDefinition;
+import org.jboss.as.controller.access.management.DelegatingConfigurableAuthorizer;
+import org.jboss.as.controller.capability.registry.RuntimeCapabilityRegistry;
+import org.jboss.as.controller.descriptions.common.ControllerResolver;
+import org.jboss.as.controller.extension.ExtensionRegistry;
+import org.jboss.as.controller.extension.ExtensionRegistryType;
+import org.jboss.as.controller.registry.ManagementResourceRegistration;
+import org.jboss.as.controller.registry.Resource;
+import org.jboss.as.domain.management.CoreManagementResourceDefinition;
+import org.jboss.as.domain.management.audit.EnvironmentNameReader;
+import org.jboss.as.domain.management.security.KeystoreAttributes;
+import org.jboss.as.subsystem.test.AbstractSubsystemTest;
+import org.jboss.as.subsystem.test.AdditionalInitialization;
+import org.jboss.as.subsystem.test.KernelServices;
+import org.jboss.as.web.WebExtension;
+import org.jboss.dmr.ModelNode;
+import org.junit.Test;
+import org.wildfly.extension.io.IOExtension;
+import org.wildfly.extension.undertow.Constants;
+import org.wildfly.extension.undertow.UndertowExtension;
+
+import java.io.File;
+
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.AUTHENTICATION;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.CORE_SERVICE;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.EXTENSION;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.MANAGEMENT;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SECURITY_REALM;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUBSYSTEM;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.TRUSTSTORE;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ *
+ * @author Stuart Douglas
+ */
+public class WebMigrateTestCase extends AbstractSubsystemTest {
+
+ public static final String UNDERTOW_SUBSYSTEM_NAME = "undertow";
+
+ public WebMigrateTestCase() {
+ super(WebExtension.SUBSYSTEM_NAME, new WebExtension());
+ }
+
+ @Test
+ public void testMigrateOperation() throws Exception {
+ String subsystemXml = readResource("subsystem-migrate-2.2.0.xml");
+ NewSubsystemAdditionalInitialization additionalInitialization = new NewSubsystemAdditionalInitialization();
+ KernelServices services = createKernelServicesBuilder(additionalInitialization).setSubsystemXml(subsystemXml).build();
+
+ ModelNode model = services.readWholeModel();
+ assertFalse(additionalInitialization.extensionAdded);
+ assertTrue(model.get(SUBSYSTEM, WebExtension.SUBSYSTEM_NAME).isDefined());
+ assertFalse(model.get(SUBSYSTEM, UNDERTOW_SUBSYSTEM_NAME).isDefined());
+
+ ModelNode migrateOp = new ModelNode();
+ migrateOp.get(OP).set("migrate");
+ migrateOp.get(OP_ADDR).add(SUBSYSTEM, WebExtension.SUBSYSTEM_NAME);
+
+ checkOutcome(services.executeOperation(migrateOp));
+
+ model = services.readWholeModel();
+
+ assertTrue(additionalInitialization.extensionAdded);
+ assertFalse(model.get(SUBSYSTEM, WebExtension.SUBSYSTEM_NAME).isDefined());
+ assertTrue(model.get(SUBSYSTEM, UNDERTOW_SUBSYSTEM_NAME).isDefined());
+
+ //make sure we have an IO subsystem
+ ModelNode ioSubsystem = model.get(SUBSYSTEM, "io");
+ assertTrue(ioSubsystem.isDefined());
+ assertTrue(ioSubsystem.get("worker", "default").isDefined());
+ assertTrue(ioSubsystem.get("buffer-pool", "default").isDefined());
+
+ ModelNode newSubsystem = model.get(SUBSYSTEM, UNDERTOW_SUBSYSTEM_NAME);
+ ModelNode newServer = newSubsystem.get("server", "default");
+ assertNotNull(newServer);
+ assertTrue(newServer.isDefined());
+ assertEquals("default-host", newServer.get(Constants.DEFAULT_HOST).asString());
+
+
+ //servlet container
+ ModelNode servletContainer = newSubsystem.get(Constants.SERVLET_CONTAINER, "default");
+ assertNotNull(servletContainer);
+ assertTrue(servletContainer.isDefined());
+ assertEquals("${prop.default-session-timeout:30}", servletContainer.get(Constants.DEFAULT_SESSION_TIMEOUT).asString());
+ assertEquals("${prop.listings:true}", servletContainer.get(Constants.DIRECTORY_LISTING).asString());
+
+ //jsp settings
+ ModelNode jsp = servletContainer.get(Constants.SETTING, Constants.JSP);
+ assertNotNull(jsp);
+ assertEquals("${prop.recompile-on-fail:true}", jsp.get(Constants.RECOMPILE_ON_FAIL).asString());
+
+ //welcome file
+ ModelNode welcome = servletContainer.get(Constants.WELCOME_FILE, "toto");
+ assertTrue(welcome.isDefined());
+
+ //mime mapping
+ ModelNode mimeMapping = servletContainer.get(Constants.MIME_MAPPING, "ogx");
+ assertTrue(mimeMapping.isDefined());
+ assertEquals("application/ogg", mimeMapping.get(Constants.VALUE).asString());
+
+ //http connector
+ ModelNode connector = newServer.get(Constants.HTTP_LISTENER, "http");
+ assertTrue(connector.isDefined());
+ assertEquals("http", connector.get(Constants.SOCKET_BINDING).asString());
+ assertEquals("${prop.enabled:true}", connector.get(Constants.ENABLED).asString());
+ assertEquals("${prop.enable-lookups:false}", connector.get(Constants.RESOLVE_PEER_ADDRESS).asString());
+ assertEquals("${prop.max-post-size:2097153}", connector.get(Constants.MAX_POST_SIZE).asString());
+ assertEquals("https", connector.get(Constants.REDIRECT_SOCKET).asString());
+
+ //https connector
+ ModelNode httpsConnector = newServer.get(Constants.HTTPS_LISTENER, "https");
+ String realmName = httpsConnector.get(Constants.SECURITY_REALM).asString();
+ assertTrue(realmName, realmName.startsWith("jbossweb-migration-security-realm"));
+ assertEquals("${prop.session-cache-size:512}", httpsConnector.get(Constants.SSL_SESSION_CACHE_SIZE).asString());
+
+ //realm name is dynamic
+ ModelNode realm = model.get(CORE_SERVICE, MANAGEMENT).get(SECURITY_REALM, realmName);
+
+ //trust store
+ ModelNode trustStore = realm.get(AUTHENTICATION, TRUSTSTORE);
+ assertEquals("${file-base}/jsse.keystore", trustStore.get(KeystoreAttributes.KEYSTORE_PATH.getName()).asString());
+
+
+ //virtual host
+ ModelNode virtualHost = newServer.get(Constants.HOST, "default-host");
+ //welcome content
+ assertEquals("welcome-content", virtualHost.get("location", "/").get(Constants.HANDLER).asString());
+
+ assertEquals("localhost", virtualHost.get("alias").asList().get(0).asString());
+
+ ModelNode accessLog = virtualHost.get(Constants.SETTING, Constants.ACCESS_LOG);
+
+ assertEquals("prefix", accessLog.get(Constants.PREFIX).asString());
+ assertEquals("true", accessLog.get(Constants.ROTATE).asString());
+ assertEquals("extended", accessLog.get(Constants.PATTERN).asString());
+
+ //sso
+ ModelNode sso = virtualHost.get(Constants.SETTING, Constants.SINGLE_SIGN_ON);
+ assertEquals("${prop.domain:myDomain}", sso.get(Constants.DOMAIN).asString());
+ assertEquals("${prop.http-only:true}", sso.get(Constants.HTTP_ONLY).asString());
+
+
+ }
+
+ private static class NewSubsystemAdditionalInitialization extends AdditionalInitialization {
+
+ UndertowExtension undertow = new UndertowExtension();
+ IOExtension io = new IOExtension();
+
+ boolean extensionAdded = false;
+
+ @Override
+ protected void initializeExtraSubystemsAndModel(ExtensionRegistry extensionRegistry, Resource rootResource, ManagementResourceRegistration rootRegistration, RuntimeCapabilityRegistry capabilityRegistry) {
+ rootRegistration.registerSubModel(new SimpleResourceDefinition(PathElement.pathElement(EXTENSION),
+ ControllerResolver.getResolver(EXTENSION), new OperationStepHandler() {
+ @Override
+ public void execute(OperationContext context, ModelNode operation) throws OperationFailedException {
+ if(!extensionAdded) {
+ extensionAdded = true;
+ undertow.initialize(extensionRegistry.getExtensionContext("org.wildfly.extension.undertow",
+ rootRegistration, ExtensionRegistryType.SERVER));
+ io.initialize(extensionRegistry.getExtensionContext("org.wildfly.extension.io",
+ rootRegistration, ExtensionRegistryType.SERVER));
+ }
+ }
+ }, null));
+ rootRegistration.registerSubModel(CoreManagementResourceDefinition.forStandaloneServer(new DelegatingConfigurableAuthorizer(), null, null, new EnvironmentNameReader() {
+ public boolean isServer() {
+ return true;
+ }
+
+ public String getServerName() {
+ return "Test";
+ }
+
+ public String getHostName() {
+ return null;
+ }
+
+ public String getProductName() {
+ return null;
+ }
+ }, null));
+ rootResource.registerChild(CoreManagementResourceDefinition.PATH_ELEMENT, Resource.Factory.create());
+ System.setProperty("file-base", new File(getClass().getClassLoader().getResource("server.keystore").getFile()).getParentFile().getAbsolutePath());
+ }
+
+ @Override
+ protected RunningMode getRunningMode() {
+ return RunningMode.ADMIN_ONLY;
+ }
+ }
+}
diff --git a/legacy/web/src/test/resources/jsse.keystore b/legacy/web/src/test/resources/jsse.keystore
new file mode 100644
index 000000000000..ec7beec053a7
Binary files /dev/null and b/legacy/web/src/test/resources/jsse.keystore differ
diff --git a/legacy/web/src/test/resources/org/jboss/as/web/test/subsystem-migrate-2.2.0.xml b/legacy/web/src/test/resources/org/jboss/as/web/test/subsystem-migrate-2.2.0.xml
new file mode 100644
index 000000000000..14c8255c8cd0
--- /dev/null
+++ b/legacy/web/src/test/resources/org/jboss/as/web/test/subsystem-migrate-2.2.0.xml
@@ -0,0 +1,101 @@
+
+
+
+
+
+
+
+
+ toto
+ ${prop.welcome.file:titi}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/legacy/web/src/test/resources/server.keystore b/legacy/web/src/test/resources/server.keystore
new file mode 100644
index 000000000000..46ad2223cd04
Binary files /dev/null and b/legacy/web/src/test/resources/server.keystore differ
diff --git a/undertow/src/main/java/org/wildfly/extension/undertow/Constants.java b/undertow/src/main/java/org/wildfly/extension/undertow/Constants.java
index 4df9fef5b586..c5226c31cff2 100644
--- a/undertow/src/main/java/org/wildfly/extension/undertow/Constants.java
+++ b/undertow/src/main/java/org/wildfly/extension/undertow/Constants.java
@@ -198,4 +198,13 @@ public interface Constants {
String ENABLE_NODES = "enable-nodes";
String DISABLE_NODES = "disable-nodes";
String STOP_NODES = "stop-nodes";
+ String DEFAULT_SESSION_TIMEOUT = "default-session-timeout";
+ String PREDICATE = "predicate";
+ String SSL_SESSION_CACHE_SIZE = "ssl-session-cache-size";
+ String SSL_SESSION_TIMEOUT = "ssl-session-timeout";
+ String VERIFY_CLIENT = "verify-client";
+ String ENABLED_CIPHER_SUITES = "enabled-cipher-suites";
+ String ENABLED_PROTOCOLS = "enabled-protocols";
+ String ENABLE_HTTP2 = "enable-http2";
+ String ENABLE_SPDY = "enable-spdy";
}
diff --git a/undertow/src/main/java/org/wildfly/extension/undertow/HttpsListenerAdd.java b/undertow/src/main/java/org/wildfly/extension/undertow/HttpsListenerAdd.java
index b6861d5975a4..9a78e00d2460 100644
--- a/undertow/src/main/java/org/wildfly/extension/undertow/HttpsListenerAdd.java
+++ b/undertow/src/main/java/org/wildfly/extension/undertow/HttpsListenerAdd.java
@@ -47,6 +47,8 @@ ListenerService extends ListenerService> createService(String name, final Stri
HttpsListenerResourceDefinition.VERIFY_CLIENT.resolveOption(context, model,builder);
HttpsListenerResourceDefinition.ENABLED_CIPHER_SUITES.resolveOption(context, model, builder);
HttpsListenerResourceDefinition.ENABLED_PROTOCOLS.resolveOption(context, model, builder);
+ HttpsListenerResourceDefinition.SSL_SESSION_CACHE_SIZE.resolveOption(context, model, builder);
+ HttpsListenerResourceDefinition.SSL_SESSION_TIMEOUT.resolveOption(context, model, builder);
OptionMap.Builder listenerBuilder = OptionMap.builder().addAll(listenerOptions);
HttpsListenerResourceDefinition.ENABLE_HTTP2.resolveOption(context, model,listenerBuilder);
diff --git a/undertow/src/main/java/org/wildfly/extension/undertow/HttpsListenerResourceDefinition.java b/undertow/src/main/java/org/wildfly/extension/undertow/HttpsListenerResourceDefinition.java
index 5a32a9ccc49f..a242345a905b 100644
--- a/undertow/src/main/java/org/wildfly/extension/undertow/HttpsListenerResourceDefinition.java
+++ b/undertow/src/main/java/org/wildfly/extension/undertow/HttpsListenerResourceDefinition.java
@@ -31,6 +31,7 @@
import org.jboss.as.controller.AttributeDefinition;
import org.jboss.as.controller.SimpleAttributeDefinition;
import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
+import org.jboss.as.controller.client.helpers.MeasurementUnit;
import org.jboss.as.controller.operations.validation.EnumValidator;
import org.jboss.as.controller.operations.validation.StringLengthValidator;
import org.jboss.as.controller.registry.AttributeAccess;
@@ -54,7 +55,7 @@ public class HttpsListenerResourceDefinition extends ListenerResourceDefinition
.setFlags(AttributeAccess.Flag.RESTART_ALL_SERVICES)
.setValidator(new StringLengthValidator(1))
.build();
- protected static final OptionAttributeDefinition VERIFY_CLIENT = OptionAttributeDefinition.builder("verify-client", SSL_CLIENT_AUTH_MODE)
+ protected static final OptionAttributeDefinition VERIFY_CLIENT = OptionAttributeDefinition.builder(Constants.VERIFY_CLIENT, SSL_CLIENT_AUTH_MODE)
.setAllowNull(true)
.setFlags(AttributeAccess.Flag.RESTART_ALL_SERVICES)
.setAllowExpression(true)
@@ -62,32 +63,35 @@ public class HttpsListenerResourceDefinition extends ListenerResourceDefinition
.setDefaultValue(new ModelNode(SslClientAuthMode.NOT_REQUESTED.name()))
.build();
- protected static final OptionAttributeDefinition ENABLED_CIPHER_SUITES = OptionAttributeDefinition.builder("enabled-cipher-suites", Options.SSL_ENABLED_CIPHER_SUITES)
+ protected static final OptionAttributeDefinition ENABLED_CIPHER_SUITES = OptionAttributeDefinition.builder(Constants.ENABLED_CIPHER_SUITES, Options.SSL_ENABLED_CIPHER_SUITES)
.setAllowNull(true)
.setFlags(AttributeAccess.Flag.RESTART_ALL_SERVICES)
.setAllowExpression(true)
.build();
- protected static final OptionAttributeDefinition ENABLED_PROTOCOLS = OptionAttributeDefinition.builder("enabled-protocols", Options.SSL_ENABLED_PROTOCOLS)
+ protected static final OptionAttributeDefinition ENABLED_PROTOCOLS = OptionAttributeDefinition.builder(Constants.ENABLED_PROTOCOLS, Options.SSL_ENABLED_PROTOCOLS)
.setAllowNull(true)
.setFlags(AttributeAccess.Flag.RESTART_ALL_SERVICES)
.setAllowExpression(true)
.build();
- protected static final OptionAttributeDefinition ENABLE_HTTP2 = OptionAttributeDefinition.builder("enable-http2", UndertowOptions.ENABLE_HTTP2)
+ protected static final OptionAttributeDefinition ENABLE_HTTP2 = OptionAttributeDefinition.builder(Constants.ENABLE_HTTP2, UndertowOptions.ENABLE_HTTP2)
.setAllowNull(true)
.setFlags(AttributeAccess.Flag.RESTART_ALL_SERVICES)
.setAllowExpression(true)
.setDefaultValue(new ModelNode(false))
.build();
- protected static final OptionAttributeDefinition ENABLE_SPDY = OptionAttributeDefinition.builder("enable-spdy", UndertowOptions.ENABLE_SPDY)
+ protected static final OptionAttributeDefinition ENABLE_SPDY = OptionAttributeDefinition.builder(Constants.ENABLE_SPDY, UndertowOptions.ENABLE_SPDY)
.setAllowNull(true)
.setFlags(AttributeAccess.Flag.RESTART_ALL_SERVICES)
.setAllowExpression(true)
.setDefaultValue(new ModelNode(false))
.build();
+ public static final OptionAttributeDefinition SSL_SESSION_CACHE_SIZE = OptionAttributeDefinition.builder(Constants.SSL_SESSION_CACHE_SIZE, Options.SSL_SERVER_SESSION_CACHE_SIZE).setAllowNull(true).setAllowExpression(true).build();
+ public static final OptionAttributeDefinition SSL_SESSION_TIMEOUT = OptionAttributeDefinition.builder(Constants.SSL_SESSION_TIMEOUT, Options.SSL_SERVER_SESSION_TIMEOUT).setMeasurementUnit(MeasurementUnit.SECONDS).setAllowNull(true).setAllowExpression(true).build();
+
private HttpsListenerResourceDefinition() {
super(UndertowExtension.HTTPS_LISTENER_PATH);
}
@@ -101,6 +105,8 @@ public Collection getAttributes() {
res.add(ENABLED_PROTOCOLS);
res.add(ENABLE_HTTP2);
res.add(ENABLE_SPDY);
+ res.add(SSL_SESSION_CACHE_SIZE);
+ res.add(SSL_SESSION_TIMEOUT);
return res;
}
diff --git a/undertow/src/main/java/org/wildfly/extension/undertow/ServletContainerDefinition.java b/undertow/src/main/java/org/wildfly/extension/undertow/ServletContainerDefinition.java
index 4503e0ca315d..d3b77b727cb1 100644
--- a/undertow/src/main/java/org/wildfly/extension/undertow/ServletContainerDefinition.java
+++ b/undertow/src/main/java/org/wildfly/extension/undertow/ServletContainerDefinition.java
@@ -95,7 +95,7 @@ class ServletContainerDefinition extends PersistentResourceDefinition {
.build();
protected static final AttributeDefinition DEFAULT_SESSION_TIMEOUT =
- new SimpleAttributeDefinitionBuilder("default-session-timeout", ModelType.INT, true)
+ new SimpleAttributeDefinitionBuilder(Constants.DEFAULT_SESSION_TIMEOUT, ModelType.INT, true)
.setFlags(AttributeAccess.Flag.RESTART_ALL_SERVICES)
.setAllowExpression(true)
.setMeasurementUnit(MeasurementUnit.MINUTES)
diff --git a/undertow/src/main/java/org/wildfly/extension/undertow/UndertowExtension.java b/undertow/src/main/java/org/wildfly/extension/undertow/UndertowExtension.java
index bad64b80c18a..e1073a617c0e 100644
--- a/undertow/src/main/java/org/wildfly/extension/undertow/UndertowExtension.java
+++ b/undertow/src/main/java/org/wildfly/extension/undertow/UndertowExtension.java
@@ -44,25 +44,26 @@
public class UndertowExtension implements Extension {
public static final String SUBSYSTEM_NAME = "undertow";
+
+ public static final PathElement SUBSYSTEM_PATH = PathElement.pathElement(SUBSYSTEM, SUBSYSTEM_NAME);
public static final PathElement PATH_HANDLERS = PathElement.pathElement(Constants.CONFIGURATION, Constants.HANDLER);
public static final PathElement PATH_FILTERS = PathElement.pathElement(Constants.CONFIGURATION, Constants.FILTER);
- protected static final PathElement PATH_JSP = PathElement.pathElement(Constants.SETTING, Constants.JSP);
- protected static final PathElement PATH_SESSION_COOKIE = PathElement.pathElement(Constants.SETTING, Constants.SESSION_COOKIE);
- protected static final PathElement PATH_PERSISTENT_SESSIONS = PathElement.pathElement(Constants.SETTING, Constants.PERSISTENT_SESSIONS);
- protected static final PathElement PATH_WEBSOCKETS = PathElement.pathElement(Constants.SETTING, Constants.WEBSOCKETS);
- protected static final PathElement PATH_MIME_MAPPING = PathElement.pathElement(Constants.MIME_MAPPING);
- protected static final PathElement PATH_WELCOME_FILE = PathElement.pathElement(Constants.WELCOME_FILE);
- protected static final PathElement SUBSYSTEM_PATH = PathElement.pathElement(SUBSYSTEM, SUBSYSTEM_NAME);
- protected static final PathElement AJP_LISTENER_PATH = PathElement.pathElement(Constants.AJP_LISTENER);
- protected static final PathElement HOST_PATH = PathElement.pathElement(Constants.HOST);
- protected static final PathElement HTTP_LISTENER_PATH = PathElement.pathElement(Constants.HTTP_LISTENER);
- protected static final PathElement HTTPS_LISTENER_PATH = PathElement.pathElement(Constants.HTTPS_LISTENER);
- protected static final PathElement PATH_SERVLET_CONTAINER = PathElement.pathElement(Constants.SERVLET_CONTAINER);
- protected static final PathElement PATH_BUFFER_CACHE = PathElement.pathElement(Constants.BUFFER_CACHE);
- protected static final PathElement PATH_LOCATION = PathElement.pathElement(Constants.LOCATION);
- protected static final PathElement SERVER_PATH = PathElement.pathElement(Constants.SERVER);
- protected static final PathElement PATH_ACCESS_LOG = PathElement.pathElement(Constants.SETTING, Constants.ACCESS_LOG);
- protected static final PathElement PATH_SSO = PathElement.pathElement(Constants.SETTING, Constants.SINGLE_SIGN_ON);
+ public static final PathElement PATH_JSP = PathElement.pathElement(Constants.SETTING, Constants.JSP);
+ public static final PathElement PATH_SESSION_COOKIE = PathElement.pathElement(Constants.SETTING, Constants.SESSION_COOKIE);
+ public static final PathElement PATH_PERSISTENT_SESSIONS = PathElement.pathElement(Constants.SETTING, Constants.PERSISTENT_SESSIONS);
+ public static final PathElement PATH_WEBSOCKETS = PathElement.pathElement(Constants.SETTING, Constants.WEBSOCKETS);
+ public static final PathElement PATH_MIME_MAPPING = PathElement.pathElement(Constants.MIME_MAPPING);
+ public static final PathElement PATH_WELCOME_FILE = PathElement.pathElement(Constants.WELCOME_FILE);
+ public static final PathElement AJP_LISTENER_PATH = PathElement.pathElement(Constants.AJP_LISTENER);
+ public static final PathElement HOST_PATH = PathElement.pathElement(Constants.HOST);
+ public static final PathElement HTTP_LISTENER_PATH = PathElement.pathElement(Constants.HTTP_LISTENER);
+ public static final PathElement HTTPS_LISTENER_PATH = PathElement.pathElement(Constants.HTTPS_LISTENER);
+ public static final PathElement PATH_SERVLET_CONTAINER = PathElement.pathElement(Constants.SERVLET_CONTAINER);
+ public static final PathElement PATH_BUFFER_CACHE = PathElement.pathElement(Constants.BUFFER_CACHE);
+ public static final PathElement PATH_LOCATION = PathElement.pathElement(Constants.LOCATION);
+ public static final PathElement SERVER_PATH = PathElement.pathElement(Constants.SERVER);
+ public static final PathElement PATH_ACCESS_LOG = PathElement.pathElement(Constants.SETTING, Constants.ACCESS_LOG);
+ public static final PathElement PATH_SSO = PathElement.pathElement(Constants.SETTING, Constants.SINGLE_SIGN_ON);
public static final PathElement BALANCER = PathElement.pathElement(Constants.BALANCER);
public static final PathElement CONTEXT = PathElement.pathElement(Constants.CONTEXT);
public static final PathElement LOAD_BALANCING_GROUP = PathElement.pathElement(Constants.LOAD_BALANCING_GROUP);
diff --git a/undertow/src/main/java/org/wildfly/extension/undertow/UndertowSubsystemParser_3_0.java b/undertow/src/main/java/org/wildfly/extension/undertow/UndertowSubsystemParser_3_0.java
index b389810dfc94..9c891e4a5248 100644
--- a/undertow/src/main/java/org/wildfly/extension/undertow/UndertowSubsystemParser_3_0.java
+++ b/undertow/src/main/java/org/wildfly/extension/undertow/UndertowSubsystemParser_3_0.java
@@ -87,7 +87,7 @@ public class UndertowSubsystemParser_3_0 extends PersistentResourceXMLParser {
builder(HttpsListenerResourceDefinition.INSTANCE)
.addAttributes(AjpListenerResourceDefinition.SOCKET_BINDING, AjpListenerResourceDefinition.WORKER, AjpListenerResourceDefinition.BUFFER_POOL, AjpListenerResourceDefinition.ENABLED)
.addAttribute(ListenerResourceDefinition.RESOLVE_PEER_ADDRESS)
- .addAttributes(HttpsListenerResourceDefinition.SECURITY_REALM, HttpsListenerResourceDefinition.VERIFY_CLIENT, HttpsListenerResourceDefinition.ENABLED_CIPHER_SUITES, HttpsListenerResourceDefinition.ENABLED_PROTOCOLS, HttpsListenerResourceDefinition.ENABLE_HTTP2, HttpsListenerResourceDefinition.ENABLE_SPDY)
+ .addAttributes(HttpsListenerResourceDefinition.SECURITY_REALM, HttpsListenerResourceDefinition.VERIFY_CLIENT, HttpsListenerResourceDefinition.ENABLED_CIPHER_SUITES, HttpsListenerResourceDefinition.ENABLED_PROTOCOLS, HttpsListenerResourceDefinition.ENABLE_HTTP2, HttpsListenerResourceDefinition.ENABLE_SPDY, HttpsListenerResourceDefinition.SSL_SESSION_CACHE_SIZE, HttpsListenerResourceDefinition.SSL_SESSION_TIMEOUT)
.addAttributes(ListenerResourceDefinition.MAX_HEADER_SIZE, ListenerResourceDefinition.MAX_ENTITY_SIZE,
ListenerResourceDefinition.BUFFER_PIPELINED_DATA, ListenerResourceDefinition.MAX_PARAMETERS, ListenerResourceDefinition.MAX_HEADERS, ListenerResourceDefinition.MAX_COOKIES, ListenerResourceDefinition.ALLOW_ENCODED_SLASH, ListenerResourceDefinition.DECODE_URL,
ListenerResourceDefinition.URL_CHARSET, ListenerResourceDefinition.ALWAYS_SET_KEEP_ALIVE, ListenerResourceDefinition.MAX_BUFFERED_REQUEST_SIZE, ListenerResourceDefinition.RECORD_REQUEST_START_TIME,
diff --git a/undertow/src/main/java/org/wildfly/extension/undertow/logging/UndertowLogger.java b/undertow/src/main/java/org/wildfly/extension/undertow/logging/UndertowLogger.java
index 2efba3d279f8..d7042e83335f 100644
--- a/undertow/src/main/java/org/wildfly/extension/undertow/logging/UndertowLogger.java
+++ b/undertow/src/main/java/org/wildfly/extension/undertow/logging/UndertowLogger.java
@@ -30,6 +30,8 @@
import java.net.InetSocketAddress;
import java.util.List;
+import org.jboss.as.controller.OperationFailedException;
+import org.jboss.as.controller.PathAddress;
import org.jboss.as.server.deployment.DeploymentUnit;
import org.jboss.as.server.deployment.DeploymentUnitProcessingException;
import org.jboss.dmr.ModelNode;
@@ -326,4 +328,18 @@ public interface UndertowLogger extends BasicLogger {
@Message(id = 76, value = "Cannot remove resource of type %s")
IllegalArgumentException cannotRemoveResourceOfType(String type);
+
+ @Message(id = 77, value = "Migrate operation only allowed in admin only mode")
+ OperationFailedException migrateOperationAllowedOnlyInAdminOnly();
+
+ @LogMessage(level = WARN)
+ @Message(id = 78, value = "Could not migrate resource %s")
+ void couldNotMigrateResource(ModelNode node);
+
+ @LogMessage(level = WARN)
+ @Message(id = 79, value = "Could not migrate attribute %s from resource %s")
+ void couldNotMigrateResource(String attribute, PathAddress node);
+
+ @Message(id = 80, value = "Could not migrate SSL connector as no SSL config is defined")
+ OperationFailedException noSslConfig();
}
diff --git a/undertow/src/main/resources/org/wildfly/extension/undertow/LocalDescriptions.properties b/undertow/src/main/resources/org/wildfly/extension/undertow/LocalDescriptions.properties
index f015415b0493..9ef1b61f7ee6 100644
--- a/undertow/src/main/resources/org/wildfly/extension/undertow/LocalDescriptions.properties
+++ b/undertow/src/main/resources/org/wildfly/extension/undertow/LocalDescriptions.properties
@@ -164,6 +164,8 @@ undertow.listener.reset-statistics=Resets all the connector statistics to zero
undertow.listener.enable-http2=Enables HTTP2 support for this listener
undertow.listener.enable-spdy=Enables SPDY support for this listener
undertow.listener.disallowed-methods=A comma separated list of HTTP methods that are not allowed
+undertow.listener.ssl-session-cache-size=The maximum number of active SSL sessions
+undertow.listener.ssl-session-timeout=The timeout for SSL sessions, in seconds
undertow.host=An Undertow host
undertow.host.add=Adds a new host
undertow.host.remove=Removes a host
diff --git a/undertow/src/main/resources/schema/wildfly-undertow_3_0.xsd b/undertow/src/main/resources/schema/wildfly-undertow_3_0.xsd
index 74a9bd0a7081..f92381c3b31f 100644
--- a/undertow/src/main/resources/schema/wildfly-undertow_3_0.xsd
+++ b/undertow/src/main/resources/schema/wildfly-undertow_3_0.xsd
@@ -160,6 +160,8 @@
+
+