/** * Copyright 2015-2016 Red Hat, Inc, and individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.wildfly.swarm.undertow; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import org.jboss.shrinkwrap.api.Archive; import org.jboss.shrinkwrap.api.ArchivePath; import org.jboss.shrinkwrap.api.Filter; import org.jboss.shrinkwrap.api.Filters; import org.jboss.shrinkwrap.api.Node; import org.jboss.shrinkwrap.api.asset.Asset; import org.jboss.shrinkwrap.impl.base.path.BasicPath; import org.wildfly.swarm.undertow.internal.DefaultWarDeploymentFactory; import org.wildfly.swarm.undertow.internal.UndertowExternalMountsAsset; /** Archive mix-in supporting static content serving for .war files. * * @author Bob McWhirter */ public interface StaticContentContainer<T extends Archive<T>> extends Archive<T> { Logger log = Logger.getLogger(StaticContentContainer.class.getName()); String EXTERNAL_MOUNT_PATH = "WEB-INF/undertow-external-mounts.conf"; /** Enable static content to be served from the root of the classpath. * * @return This archive. */ default T staticContent() { return staticContent(""); } /** Enable static content to be served from a given base in the classpath. * * @param base The path prefix to use for static content. * @return */ @SuppressWarnings("unchecked") default T staticContent(String base) { //as(WARArchive.class).addModule("org.wildfly.swarm.undertow", "runtime"); try { // Add all the static content from the current app to the archive Archive allResources = DefaultWarDeploymentFactory.archiveFromCurrentApp(); // Here we define static as basically anything that's not a // Java class file or under WEB-INF or META-INF mergeIgnoringDuplicates(allResources, base, Filters.exclude(".*\\.class$")); } catch (Exception ex) { log.log(Level.WARNING, "Error setting up static resources", ex); } Node node = get(EXTERNAL_MOUNT_PATH); UndertowExternalMountsAsset asset; if (node == null) { asset = new UndertowExternalMountsAsset(); add(asset, EXTERNAL_MOUNT_PATH); } else { Asset tempAsset = node.getAsset(); if (!(tempAsset instanceof UndertowExternalMountsAsset)) { asset = new UndertowExternalMountsAsset(tempAsset.openStream()); add(asset, EXTERNAL_MOUNT_PATH); } else { asset = (UndertowExternalMountsAsset) node.getAsset(); } } // Add external mounts for static content so changes are picked up // immediately during development Path webResources = Paths.get(System.getProperty("user.dir"), "src", "main", "webapp"); if (base != null) { webResources = webResources.resolve(base); } if (Files.exists(webResources)) { asset.externalMount(webResources.toString()); } webResources = Paths.get(System.getProperty("user.dir"), "src", "main", "resources"); if (base != null) { webResources = webResources.resolve(base); } if (Files.exists(webResources)) { asset.externalMount(webResources.toString()); } return (T) this; } @SuppressWarnings("unchecked") default T mergeIgnoringDuplicates(Archive<?> source, String base, Filter<ArchivePath> filter) { if (!base.startsWith("/")) { base = "/" + base; } // Get existing contents from source archive final Map<ArchivePath, Node> sourceContent = source.getContent(); // Add each asset from the source archive for (final Map.Entry<ArchivePath, Node> contentEntry : sourceContent.entrySet()) { final Node node = contentEntry.getValue(); ArchivePath nodePath = contentEntry.getKey(); if (!nodePath.get().startsWith(base)) { continue; } if (!filter.include(nodePath)) { continue; } if (contains(nodePath)) { continue; } nodePath = new BasicPath(nodePath.get().replaceFirst(base, "")); // Delegate if (node.getAsset() == null) { addAsDirectory(nodePath); } else { add(node.getAsset(), nodePath); } } return (T) this; } }