/* * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Middleware LLC. * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU * Lesser General Public License, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this distribution; if not, write to: * Free Software Foundation, Inc. * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ package org.hibernate.ejb.packaging; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URISyntaxException; import java.net.URL; import org.hibernate.ejb.internal.EntityManagerMessageLogger; import org.hibernate.internal.util.StringHelper; import org.jboss.logging.Logger; /** * @author Emmanuel Bernard */ public class JarVisitorFactory { private static final EntityManagerMessageLogger LOG = Logger.getMessageLogger(EntityManagerMessageLogger.class, JarVisitorFactory.class.getName()); /** * Get the JAR URL of the JAR containing the given entry * Method used in a non managed environment * * @param url URL pointing to the known file in the JAR * @param entry file known to be in the JAR * @return the JAR URL * @throws IllegalArgumentException if none URL is found * TODO move to a ScannerHelper service? */ public static URL getJarURLFromURLEntry(URL url, String entry) throws IllegalArgumentException { URL jarUrl; String file = url.getFile(); if ( ! entry.startsWith( "/" ) ) entry = "/" + entry; file = file.substring( 0, file.length() - entry.length() ); if ( file.endsWith( "!" ) ) file = file.substring( 0, file.length() - 1 ); try { String protocol = url.getProtocol(); if ( "jar".equals( protocol ) || "wsjar".equals( protocol ) ) { //Websphere has it's own way //Original URL is like jar:protocol jarUrl = new URL( file ); if ( "file".equals( jarUrl.getProtocol() ) ) { //not escaped, need to voodoo if ( file.indexOf( ' ' ) != -1 ) { //not escaped, need to voodoo jarUrl = new File( jarUrl.getFile() ).toURI().toURL(); //goes by toURI to escape the path } } //otherwise left as is } else if ( "zip".equals( protocol ) //Weblogic has it's own way || "code-source".equals( url.getProtocol() ) //OC4J prevent ejb.jar access (ie everything without path) || "file".equals( protocol ) //if no wrapping is done ) { //we have extracted the zip file, so it should be read as a file if ( file.indexOf( ' ' ) != -1 ) { //not escaped, need to voodoo jarUrl = new File(file).toURI().toURL(); //goes by toURI to escape the path } else { jarUrl = new File(file).toURL(); } } else { try { //We reconstruct the URL probably to make it work in some specific environments //Forgot the exact details, sorry (and the Git history does not help) jarUrl = new URL( protocol, url.getHost(), url.getPort(), file ); } //HHH-6442: Arquilian catch ( final MalformedURLException murle ) { //Just use the provided URL as-is, likely it has a URLStreamHandler //associated w/ the instance jarUrl = url; } } } catch (MalformedURLException e) { throw new IllegalArgumentException( "Unable to determine JAR Url from " + url + ". Cause: " + e.getMessage() ); } LOG.trace("JAR URL from URL Entry: " + url + " >> " + jarUrl); return jarUrl; } /** * get the URL from a given path string * * @throws IllegalArgumentException is something goes wrong * TODO move to a ScannerHelper service? */ public static URL getURLFromPath(String jarPath) { URL jarUrl; try { //is it an url jarUrl = new URL( jarPath ); } catch ( MalformedURLException e) { try { //consider it as a file path jarUrl = new URL( "file:" + jarPath ); } catch (MalformedURLException ee) { throw new IllegalArgumentException( "Unable to find jar:" + jarPath, ee ); } } return jarUrl; } /** * Get a JarVisitor to the jar <code>jarPath</code> applying the given filters * * Method used in a non-managed environment * * @throws IllegalArgumentException if the jarPath is incorrect */ public static JarVisitor getVisitor(String jarPath, Filter[] filters) throws IllegalArgumentException { File file = new File( jarPath ); if ( file.isFile() ) { return new InputStreamZippedJarVisitor( jarPath, filters ); } else { return new ExplodedJarVisitor( jarPath, filters ); } } /** * Build a JarVisitor on the given JAR URL applying the given filters * * @throws IllegalArgumentException if the URL is malformed */ public static JarVisitor getVisitor(URL jarUrl, Filter[] filters) throws IllegalArgumentException { return getVisitor( jarUrl, filters, "" ); } public static JarVisitor getVisitor(URL jarUrl, Filter[] filters, String entry) throws IllegalArgumentException { String protocol = jarUrl.getProtocol(); if ( "jar".equals( protocol ) ) { return new JarProtocolVisitor( jarUrl, filters, entry ); } else if ( StringHelper.isEmpty( protocol ) || "file".equals( protocol ) ) { File file; try { final String filePart = jarUrl.getFile(); if ( filePart != null && filePart.indexOf( ' ' ) != -1 ) { //unescaped (from the container), keep as is file = new File( jarUrl.getFile() ); } else { file = new File( jarUrl.toURI().getSchemeSpecificPart() ); } } catch (URISyntaxException e) { throw new IllegalArgumentException( "Unable to visit JAR " + jarUrl + ". Cause: " + e.getMessage(), e ); } if ( file.isDirectory() ) { return new ExplodedJarVisitor( jarUrl, filters, entry ); } else { return new FileZippedJarVisitor( jarUrl, filters, entry ); } } else { //let's assume the url can return the jar as a zip stream return new InputStreamZippedJarVisitor( jarUrl, filters, entry ); } } public static byte[] getBytesFromInputStream(InputStream inputStream) throws IOException { int size; byte[] tmpByte = new byte[ 4096 ]; byte[] entryBytes = new byte[0]; for ( ; ; ) { size = inputStream.read( tmpByte ); if ( size == -1 ) break; byte[] current = new byte[ entryBytes.length + size ]; System.arraycopy( entryBytes, 0, current, 0, entryBytes.length ); System.arraycopy( tmpByte, 0, current, entryBytes.length, size ); entryBytes = current; } return entryBytes; } }