/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.catalina.webresources;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.Set;
import java.util.jar.Manifest;

import org.apache.catalina.LifecycleException;
import org.apache.catalina.WebResource;
import org.apache.catalina.WebResourceRoot;
import org.apache.catalina.WebResourceRoot.ResourceSetType;
import org.apache.catalina.util.ResourceSet;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;

Represents a WebResourceSet based on a directory.
/** * Represents a {@link org.apache.catalina.WebResourceSet} based on a directory. */
public class DirResourceSet extends AbstractFileResourceSet { private static final Log log = LogFactory.getLog(DirResourceSet.class);
A no argument constructor is required for this to work with the digester.
/** * A no argument constructor is required for this to work with the digester. */
public DirResourceSet() { super("/"); }
Creates a new WebResourceSet based on a directory.
Params:
  • root – The WebResourceRoot this new WebResourceSet will be added to.
  • webAppMount – The path within the web application at which this WebResourceSet will be mounted. For example, to add a directory of JARs to a web application, the directory would be mounted at "/WEB-INF/lib/"
  • base – The absolute path to the directory on the file system from which the resources will be served.
  • internalPath – The path within this new WebResourceSet where resources will be served from.
/** * Creates a new {@link org.apache.catalina.WebResourceSet} based on a * directory. * * @param root The {@link WebResourceRoot} this new * {@link org.apache.catalina.WebResourceSet} will * be added to. * @param webAppMount The path within the web application at which this * {@link org.apache.catalina.WebResourceSet} will * be mounted. For example, to add a directory of * JARs to a web application, the directory would * be mounted at "/WEB-INF/lib/" * @param base The absolute path to the directory on the file * system from which the resources will be served. * @param internalPath The path within this new {@link * org.apache.catalina.WebResourceSet} where * resources will be served from. */
public DirResourceSet(WebResourceRoot root, String webAppMount, String base, String internalPath) { super(internalPath); setRoot(root); setWebAppMount(webAppMount); setBase(base); if (root.getContext().getAddWebinfClassesResources()) { File f = new File(base, internalPath); f = new File(f, "/WEB-INF/classes/META-INF/resources"); if (f.isDirectory()) { root.createWebResourceSet(ResourceSetType.RESOURCE_JAR, "/", f.getAbsolutePath(), null, "/"); } } if (getRoot().getState().isAvailable()) { try { start(); } catch (LifecycleException e) { throw new IllegalStateException(e); } } } @Override public WebResource getResource(String path) { checkPath(path); String webAppMount = getWebAppMount(); WebResourceRoot root = getRoot(); if (path.startsWith(webAppMount)) { File f = file(path.substring(webAppMount.length()), false); if (f == null) { return new EmptyResource(root, path); } if (!f.exists()) { return new EmptyResource(root, path, f); } if (f.isDirectory() && path.charAt(path.length() - 1) != '/') { path = path + '/'; } return new FileResource(root, path, f, isReadOnly(), getManifest()); } else { return new EmptyResource(root, path); } } @Override public String[] list(String path) { checkPath(path); String webAppMount = getWebAppMount(); if (path.startsWith(webAppMount)) { File f = file(path.substring(webAppMount.length()), true); if (f == null) { return EMPTY_STRING_ARRAY; } String[] result = f.list(); if (result == null) { return EMPTY_STRING_ARRAY; } else { return result; } } else { if (!path.endsWith("/")) { path = path + "/"; } if (webAppMount.startsWith(path)) { int i = webAppMount.indexOf('/', path.length()); if (i == -1) { return new String[] {webAppMount.substring(path.length())}; } else { return new String[] { webAppMount.substring(path.length(), i)}; } } return EMPTY_STRING_ARRAY; } } @Override public Set<String> listWebAppPaths(String path) { checkPath(path); String webAppMount = getWebAppMount(); ResourceSet<String> result = new ResourceSet<>(); if (path.startsWith(webAppMount)) { File f = file(path.substring(webAppMount.length()), true); if (f != null) { File[] list = f.listFiles(); if (list != null) { for (File entry : list) { StringBuilder sb = new StringBuilder(path); if (path.charAt(path.length() - 1) != '/') { sb.append('/'); } sb.append(entry.getName()); if (entry.isDirectory()) { sb.append('/'); } result.add(sb.toString()); } } } } else { if (!path.endsWith("/")) { path = path + "/"; } if (webAppMount.startsWith(path)) { int i = webAppMount.indexOf('/', path.length()); if (i == -1) { result.add(webAppMount + "/"); } else { result.add(webAppMount.substring(0, i + 1)); } } } result.setLocked(true); return result; } @Override public boolean mkdir(String path) { checkPath(path); if (isReadOnly()) { return false; } String webAppMount = getWebAppMount(); if (path.startsWith(webAppMount)) { File f = file(path.substring(webAppMount.length()), false); if (f == null) { return false; } return f.mkdir(); } else { return false; } } @Override public boolean write(String path, InputStream is, boolean overwrite) { checkPath(path); if (is == null) { throw new NullPointerException( sm.getString("dirResourceSet.writeNpe")); } if (isReadOnly()) { return false; } // write() is meant to create a file so ensure that the path doesn't // end in '/' if (path.endsWith("/")) { return false; } File dest = null; String webAppMount = getWebAppMount(); if (path.startsWith(webAppMount)) { dest = file(path.substring(webAppMount.length()), false); if (dest == null) { return false; } } else { return false; } if (dest.exists() && !overwrite) { return false; } try { if (overwrite) { Files.copy(is, dest.toPath(), StandardCopyOption.REPLACE_EXISTING); } else { Files.copy(is, dest.toPath()); } } catch (IOException ioe) { return false; } return true; } @Override protected void checkType(File file) { if (file.isDirectory() == false) { throw new IllegalArgumentException(sm.getString("dirResourceSet.notDirectory", getBase(), File.separator, getInternalPath())); } } //-------------------------------------------------------- Lifecycle methods @Override protected void initInternal() throws LifecycleException { super.initInternal(); // Is this an exploded web application? if (getWebAppMount().equals("")) { // Look for a manifest File mf = file("META-INF/MANIFEST.MF", true); if (mf != null && mf.isFile()) { try (FileInputStream fis = new FileInputStream(mf)) { setManifest(new Manifest(fis)); } catch (IOException e) { log.warn(sm.getString("dirResourceSet.manifestFail", mf.getAbsolutePath()), e); } } } } }