/* * 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.deltaspike.test.utils; import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.spec.JavaArchive; import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.List; import java.util.UUID; import java.util.logging.Logger; /** * Lots of neat little helpers to more easily create JavaArchives from marker files on the classpath. * This should finally get moved to ShrinkWrap core! * * TODO This class should get moved to ShrinkWrap itself! */ public class ShrinkWrapArchiveUtil { private static final Logger LOG = Logger.getLogger(ShrinkWrapArchiveUtil.class.getName()); private ShrinkWrapArchiveUtil() { // private ct for utility class } /** * Resolve all markerFiles from the current ClassPath and package the root nodes * into a JavaArchive. * * @param classLoader to use * @param markerFile finding this marker file will trigger creating the JavaArchive. * @param includeIfPackageExists if not null, we will only create JavaArchives if the given package exists * @param excludeIfPackageExists if not null, we will <b>not</b> create JavaArchives if the given package exists. * This has a higher precedence than includeIfPackageExists. */ public static JavaArchive[] getArchives(ClassLoader classLoader, String markerFile, String[] includeIfPackageExists, String[] excludeIfPackageExists, String archiveName) { if (classLoader == null) { classLoader = ShrinkWrapArchiveUtil.class.getClassLoader(); } try { Enumeration<URL> foundFiles = classLoader.getResources(markerFile); List<JavaArchive> archives = new ArrayList<JavaArchive>(); int numArchives = 0; while (foundFiles.hasMoreElements()) { URL foundFile = foundFiles.nextElement(); LOG.fine("Evaluating Java ClassPath URL " + foundFile.toExternalForm()); String suffix = (numArchives == 0) ? "" : Integer.toString(numArchives); JavaArchive archive = createArchive(foundFile, markerFile, includeIfPackageExists, excludeIfPackageExists, archiveName + suffix); if (archive != null) { LOG.info("Test " + getTestName() + " Adding Java ClassPath URL as JavaArchive " + foundFile.toExternalForm()); archives.add(archive); numArchives++; } } return archives.toArray(new JavaArchive[archives.size()]); } catch (IOException ioe) { throw new RuntimeException(ioe); } } private static JavaArchive createArchive(URL foundFile, String markerFile, String[] includeIfPackageExists, String[] excludeIfPackageExists, String archiveName) throws IOException { String urlString = foundFile.toString(); int idx = urlString.lastIndexOf(markerFile); urlString = urlString.substring(0, idx); String jarUrlPath = isJarUrl(urlString); if (jarUrlPath != null) { JavaArchive foundJar = ShrinkWrap.createFromZipFile(JavaArchive.class, new File(URI.create(jarUrlPath))); if (excludeIfPackageExists != null) { for (String excludePackage : excludeIfPackageExists) { if (foundJar.contains(excludePackage.replaceAll("\\.", "\\/"))) { return null; } } } if (includeIfPackageExists != null) { for (String includePackage : includeIfPackageExists) { if (foundJar.contains(includePackage.replaceAll("\\.", "\\/"))) { return foundJar; } } } return null; // couldn't find any jar } else { File f = new File( (new URL(ensureCorrectUrlFormat(urlString))).getFile() ); if (!f.exists()) { // try a fallback if the URL contains %20 -> spaces if (urlString.contains("%20")) { urlString = urlString.replaceAll("%20", " "); f = new File( (new URL(ensureCorrectUrlFormat(urlString))).getFile() ); } } return addFileArchive(f, includeIfPackageExists, excludeIfPackageExists, archiveName); } } private static JavaArchive addFileArchive(File archiveBasePath, String[] includeIfPackageExists, String[] excludeIfPackageExists, String archiveName) throws IOException { if (!archiveBasePath.exists()) { return null; } if (archiveName == null) { archiveName = UUID.randomUUID().toString(); } JavaArchive ret = null; JavaArchive javaArchive = ShrinkWrap.create(JavaArchive.class, archiveName + ".jar"); if (includeIfPackageExists == null) { // no include rule, thus add it immediately ret = javaArchive; } int basePathLength = archiveBasePath.getAbsolutePath().length() + 1; for (File archiveEntry : collectArchiveEntries(archiveBasePath) ) { String entryName = archiveEntry.getAbsolutePath().substring(basePathLength); // exclude rule if (excludeIfPackageExists(entryName, excludeIfPackageExists)) { continue; } // include rule if (ret == null && includeIfPackageExists(entryName, includeIfPackageExists)) { ret = javaArchive; } if (entryName.endsWith(".class")) { String className = pathToClassName(entryName.substring(0, entryName.length() - (".class".length()))); try { javaArchive.addClass(className); } catch (Throwable t) { LOG.info("Ignoring class " + className + " due to " + t.getMessage()); } } else { javaArchive.addAsResource(archiveEntry, entryName.replace('\\', '/')); } } return ret; } private static List<File> collectArchiveEntries(File archiveBasePath) { if (archiveBasePath.isDirectory()) { List<File> archiveEntries = new ArrayList<File>(); File[] files = archiveBasePath.listFiles(); for (File file : files) { if (file.isDirectory()) { archiveEntries.addAll(collectArchiveEntries(file)); } else { archiveEntries.add(file); } } return archiveEntries; } return Collections.emptyList(); } private static boolean excludeIfPackageExists(String jarEntryName, String[] excludeOnPackages) { if (excludeOnPackages != null) { String packageName = pathToClassName(jarEntryName); for (String excludeOnPackage : excludeOnPackages) { if (packageName.startsWith(excludeOnPackage)) { return true; } } } return false; } private static boolean includeIfPackageExists(String jarEntryName, String[] includeOnPackages) { if (includeOnPackages == null ) { return true; } String packageName = pathToClassName(jarEntryName); for (String includeOnPackage : includeOnPackages) { if (packageName.startsWith(includeOnPackage)) { return true; } } return false; } /** * check if the given url path is a Jar * @param urlPath to check */ private static String isJarUrl(String urlPath) { // common prefixes of the url are: jar: (tomcat), zip: (weblogic) and wsjar: (websphere) final int jarColon = urlPath.indexOf(':'); if (urlPath.endsWith("!/") && jarColon > 0) { urlPath = urlPath.substring(jarColon + 1, urlPath.length() - 2); return urlPath; } return null; } private static String ensureCorrectUrlFormat(String url) { //fix for wls if (!url.startsWith("file:/")) { url = "file:/" + url; } return url; } private static String pathToClassName(String pathName) { return pathName.replace('/', '.').replace('\\', '.'); // replace unix and windows separators } public static String getTestName() { StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); String testName = "unknown"; for (StackTraceElement ste : stackTraceElements) { if (ste.getClassName().contains("Test")) { testName = ste.getClassName(); break; } } return testName; } }