| // |
| // ======================================================================== |
| // Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd. |
| // ------------------------------------------------------------------------ |
| // All rights reserved. This program and the accompanying materials |
| // are made available under the terms of the Eclipse Public License v1.0 |
| // and Apache License v2.0 which accompanies this distribution. |
| // |
| // The Eclipse Public License is available at |
| // http://www.eclipse.org/legal/epl-v10.html |
| // |
| // The Apache License v2.0 is available at |
| // http://www.opensource.org/licenses/apache2.0.php |
| // |
| // You may elect to redistribute this code under either of these licenses. |
| // ======================================================================== |
| // |
| |
| package org.eclipse.jetty.maven.plugin; |
| |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| import java.net.URL; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.jar.JarEntry; |
| import java.util.jar.JarInputStream; |
| import java.util.jar.Manifest; |
| |
| import org.codehaus.plexus.util.SelectorUtils; |
| import org.eclipse.jetty.util.IO; |
| import org.eclipse.jetty.util.URIUtil; |
| import org.eclipse.jetty.util.log.Log; |
| import org.eclipse.jetty.util.log.Logger; |
| import org.eclipse.jetty.util.resource.JarResource; |
| |
| |
| |
| /** |
| * SelectiveJarResource |
| * |
| * Selectively copies resources from a jar file based on includes/excludes. |
| * |
| */ |
| public class SelectiveJarResource extends JarResource |
| { |
| private static final Logger LOG = Log.getLogger(SelectiveJarResource.class); |
| public static final List<String> DEFAULT_INCLUDES = Arrays.asList(new String[]{"**"});// No includes supplied, so set it to 'matches all' |
| public static final List<String> DEFAULT_EXCLUDES = Collections.emptyList(); //No includes, set to no exclusions |
| |
| List<String> _includes = null; |
| List<String> _excludes = null; |
| boolean _caseSensitive = false; |
| |
| public SelectiveJarResource(URL url) |
| { |
| super(url); |
| } |
| |
| public SelectiveJarResource(URL url, boolean useCaches) |
| { |
| super(url, useCaches); |
| } |
| |
| public void setCaseSensitive (boolean caseSensitive) |
| { |
| _caseSensitive = caseSensitive; |
| } |
| |
| public void setIncludes (List<String> patterns) |
| { |
| _includes = patterns; |
| } |
| |
| |
| public void setExcludes (List<String> patterns) |
| { |
| _excludes = patterns; |
| } |
| |
| |
| protected boolean isIncluded (String name) |
| { |
| for (String include:_includes) |
| { |
| if (SelectorUtils.matchPath(include, name, _caseSensitive)) |
| { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| protected boolean isExcluded (String name) |
| { |
| for (String exclude:_excludes) |
| { |
| if (SelectorUtils.matchPath (exclude, name, _caseSensitive)) |
| { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| |
| |
| |
| /** |
| * @see org.eclipse.jetty.util.resource.JarResource#copyTo(java.io.File) |
| */ |
| @Override |
| public void copyTo(File directory) throws IOException |
| { |
| if (_includes == null) |
| _includes = DEFAULT_INCLUDES; |
| if (_excludes == null) |
| _excludes = DEFAULT_EXCLUDES; |
| |
| //Copy contents of the jar file to the given directory, |
| //using the includes and excludes patterns to control which |
| //parts of the jar file are copied |
| if (!exists()) |
| return; |
| |
| String urlString = this.getURL().toExternalForm().trim(); |
| int endOfJarUrl = urlString.indexOf("!/"); |
| int startOfJarUrl = (endOfJarUrl >= 0?4:0); |
| |
| if (endOfJarUrl < 0) |
| throw new IOException("Not a valid jar url: "+urlString); |
| |
| URL jarFileURL = new URL(urlString.substring(startOfJarUrl, endOfJarUrl)); |
| |
| try (InputStream is = jarFileURL.openConnection().getInputStream(); |
| JarInputStream jin = new JarInputStream(is)) |
| { |
| JarEntry entry; |
| |
| while((entry=jin.getNextJarEntry())!=null) |
| { |
| String entryName = entry.getName(); |
| |
| LOG.debug("Looking at "+entryName); |
| String dotCheck = entryName.replace('\\', '/'); |
| dotCheck = URIUtil.canonicalPath(dotCheck); |
| if (dotCheck == null) |
| { |
| LOG.info("Invalid entry: "+entryName); |
| continue; |
| } |
| |
| File file=new File(directory,entryName); |
| |
| if (entry.isDirectory()) |
| { |
| if (isIncluded(entryName)) |
| { |
| if (!isExcluded(entryName)) |
| { |
| // Make directory |
| if (!file.exists()) |
| file.mkdirs(); |
| } |
| else |
| LOG.debug("{} dir is excluded", entryName); |
| } |
| else |
| LOG.debug("{} dir is NOT included", entryName); |
| } |
| else |
| { |
| //entry is a file, is it included? |
| if (isIncluded(entryName)) |
| { |
| if (!isExcluded(entryName)) |
| { |
| // make directory (some jars don't list dirs) |
| File dir = new File(file.getParent()); |
| if (!dir.exists()) |
| dir.mkdirs(); |
| |
| // Make file |
| try (OutputStream fout = new FileOutputStream(file)) |
| { |
| IO.copy(jin,fout); |
| } |
| |
| // touch the file. |
| if (entry.getTime()>=0) |
| file.setLastModified(entry.getTime()); |
| } |
| else |
| LOG.debug("{} file is excluded", entryName); |
| } |
| else |
| LOG.debug("{} file is NOT included", entryName); |
| } |
| } |
| |
| Manifest manifest = jin.getManifest(); |
| if (manifest != null) |
| { |
| if (isIncluded("META-INF") && !isExcluded("META-INF")) |
| { |
| File metaInf = new File (directory, "META-INF"); |
| metaInf.mkdir(); |
| File f = new File(metaInf, "MANIFEST.MF"); |
| try (OutputStream fout = new FileOutputStream(f)) |
| { |
| manifest.write(fout); |
| } |
| } |
| } |
| } |
| } |
| |
| } |