docs: public void copyDirectory(File destination) throws IOException {
          Preconditions.checkState(destination.exists() && destination.isDirectory(), "Destination directory must exist and be a directory: %s", destination);
  
  
          URL url = this.getUrl();
  
          if (isJarURL(url)) {
              /*
                  This is actually request for file, that's packed into jar. Probably the current one, but that doesn't matters.
               */
              InputStream stream = null;
              ZipFile zipFile = null;
              try {
                  GetStreamFromZip getStreamFromZip = new GetStreamFromZip(url, path).invoke();
                  ZipEntry entry = getStreamFromZip.getEntry();
                  stream = getStreamFromZip.getStream();
                  zipFile = getStreamFromZip.getZipFile();
  
                  Preconditions.checkState(entry.isDirectory(), "Source must be a directory: %s", entry.getName());
  
                  String pathNoSlash = this.path;
                  if(pathNoSlash.endsWith("/") || pathNoSlash.endsWith("\\")){
                      pathNoSlash = pathNoSlash.substring(0, pathNoSlash.length()-1);
                  }
  
                  Enumeration<? extends ZipEntry> entries = zipFile.entries();
                  while(entries.hasMoreElements()){
                      ZipEntry e = entries.nextElement();
                      String name = e.getName();
                      if(name.startsWith(pathNoSlash) && name.length() > pathNoSlash.length() && (name.charAt(pathNoSlash.length()) == '/' || name.charAt(pathNoSlash.length()) == '\\')){  //second condition: to avoid "/dir/a/" and "/dir/abc/" both matching startsWith
  
                          String relativePath = name.substring(this.path.length());
  
                          File extractTo = new File(destination, relativePath);
                          if(e.isDirectory()){
                              extractTo.mkdirs();
                          } else {
                              try(BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(extractTo))){
                                  InputStream is = getInputStream(name, clazz, classLoader);
                                  IOUtils.copy(is, bos);
                              }
                          }
                      }
                  }
  
                  stream.close();
                  zipFile.close();
              } catch (Exception e) {
                  throw new RuntimeException(e);
              } finally {
                  if(stream != null)
                      IOUtils.closeQuietly(stream);
                  if(zipFile != null)
                      IOUtils.closeQuietly(zipFile);
              }
  
          } else {
              File source;
              try{
                  source = new File(url.toURI());
              } catch (URISyntaxException e) {
                  throw new IOException("Error converting URL to a URI - path may be invalid? Path=" + url);
              }
              Preconditions.checkState(source.isDirectory(), "Source must be a directory: %s", source);
              Preconditions.checkState(destination.exists() && destination.isDirectory(), "Destination must be a directory and must exist: %s", destination);
              FileUtils.copyDirectory(source, destination);
          }
      }