/* * Copyright (C) 2009 Red Hat, Inc. and/or its affiliates. * * 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.jboss.errai.common.metadata; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.net.URL; import java.util.UUID; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; /** * A set of utilities for processing a {@link DeploymentContext} * * @author Heiko Braun <hbraun@redhat.com> \ */ public class PackagingUtil { private static final Logger log = LoggerFactory.getLogger("ClasspathScanning"); public static File identifyDeployment(final URL url) { String actualFilePath = url.getPath(); if (actualFilePath.startsWith("file:")) { actualFilePath = actualFilePath.substring(5); } final int nestedSeperator = actualFilePath.indexOf('!'); if (nestedSeperator != -1) { actualFilePath = actualFilePath.substring(0, nestedSeperator); } log.debug("scanning inside: " + actualFilePath); return findActualDeploymentFile(new File(actualFilePath)); } static File findActualDeploymentFile(File start) { int pivotPoint; String rootPath = start.getPath(); do { start = new File(rootPath); rootPath = rootPath.substring(0, (pivotPoint = rootPath.lastIndexOf(File.separator)) < 0 ? 0 : pivotPoint); } while (!start.exists() && pivotPoint > 0); return start; } static void process(final DeploymentContext ctx) { for (final URL url : ctx.getConfigUrls()) { final File file = PackagingUtil.identifyDeployment(url); /** * several config urls may derive from the same archive * don't process them twice */ if (!ctx.hasProcessed(file)) { ctx.markProcessed(file); if (file.getName().endsWith(".ear")){ PackagingUtil.processNestedZip(file, ctx); } } } } private static void processNestedZip(final File file, final DeploymentContext ctx) { try { if (file.getName().matches(".+\\.(ear|war|sar)$") && !file.isDirectory()) // process only certain deployment types { if (file.getName().endsWith(".war")) ctx.getSubContexts().put(file.getName(), file); // WEB-INF/classes final ZipInputStream zipFile = new ZipInputStream(new FileInputStream(file)); ZipEntry zipEntry; try { while ((zipEntry = zipFile.getNextEntry()) != null) { if (zipEntry.getName().matches(".+\\.(zip|jar|war)$")) // expand nested zip archives { if (!ctx.getSubContexts().containsKey(zipEntry.getName())) { final File tmpUnZip = expandZipEntry(zipFile, zipEntry, ctx); ctx.getSubContexts().put(zipEntry.getName(), tmpUnZip); processNestedZip(tmpUnZip, ctx); } } } } finally { zipFile.close(); } } } catch (Exception e) { throw new RuntimeException("Failed to process nested zip", e); } } protected static File expandZipEntry(final ZipInputStream stream, final ZipEntry entry, final DeploymentContext ctx) { final String tmpUUID = "erraiBootstrap_" + UUID.randomUUID().toString().replaceAll("\\-", "_"); final String tmpDir = System.getProperty("java.io.tmpdir") + "/" + tmpUUID; final int idx = entry.getName().lastIndexOf('/'); final String tmpFileName = tmpDir + "/" + entry.getName().substring(idx == -1 ? 0 : idx); try { final File tmpDirFile = new File(tmpDir); if (!tmpDirFile.exists() && !tmpDirFile.mkdirs()) { throw new RuntimeException("unable to create temporary directory: " + tmpDirFile.getAbsolutePath()); } ctx.markTmpFile(tmpDirFile); final File newFile = new File(tmpFileName); final FileOutputStream outStream = new FileOutputStream(newFile); final byte[] buf = new byte[1024]; int read; while ((read = stream.read(buf)) != -1) { outStream.write(buf, 0, read); } outStream.flush(); outStream.close(); return newFile; } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new RuntimeException("Error reading from stream", e); } } }