blob: c9db329d03208ee820b2254ea4f4402a87e80441 [file] [log] [blame]
/*
* Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.internal.jpa.deployment;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.JarURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarInputStream;
import java.util.logging.Logger;
import java.util.logging.Level;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.jpa.Archive;
import org.eclipse.persistence.jpa.ArchiveFactory;
/**
* This class is written to deal with various URLs that can be returned by
* {@link jakarta.persistence.spi.PersistenceUnitInfo#getPersistenceUnitRootUrl()}
*
* @author Sanjeeb.Sahoo@Sun.COM
*/
public class ArchiveFactoryImpl implements ArchiveFactory {
/*
* Implementation Note: This class does not have any dependency on either
* EclipseLink or GlassFish implementation classes. Please retain this separation.
*/
protected Logger logger;
@SuppressWarnings("deprecation")
public ArchiveFactoryImpl() {
this(Logger.global);
}
public ArchiveFactoryImpl(Logger logger) {
this.logger = logger;
}
@Override
public Archive createArchive(URL rootUrl, Map properties) throws URISyntaxException, IOException {
return createArchive(rootUrl, null, properties);
}
@Override
public Archive createArchive(URL rootUrl, String descriptorLocation, Map properties) throws URISyntaxException, IOException {
logger.entering("ArchiveFactoryImpl", "createArchive", new Object[]{rootUrl, descriptorLocation});
if (rootUrl == null) {
return null;
}
Archive result = null;
String protocol = rootUrl.getProtocol();
logger.logp(Level.FINER, "ArchiveFactoryImpl", "createArchive", "protocol = {0}", protocol);
if ("file".equals(protocol)) {
URI uri = Helper.toURI(rootUrl);
File f;
try {
// Attempt to create the file with the uri. The pre-conditions
// are checked in the constructor and an exception is thrown
// if the uri does not meet them.
f = new File(uri);
} catch (IllegalArgumentException e) {
// Invalid uri for File. Go our back up route of using the
// path from the url.
f = new File(rootUrl.getPath());
}
if (f.isDirectory()) {
// e.g. file:/tmp/a_ear/ejb_jar
result = new DirectoryArchive(f, descriptorLocation);
} else {
// e.g. file:/tmp/a_ear/lib/pu.jarlo
// It's not a directory. Then it must be a jar file.
result = new JarFileArchive(rootUrl, new JarFile(f), descriptorLocation);
}
} else if ("jar".equals(protocol)) { // NOI18N
JarURLConnection conn = (JarURLConnection) rootUrl.openConnection();
conn.setUseCaches(false);
JarEntry je = conn.getJarEntry();
if (je == null) {
// e.g. jar:file:/tmp/a_ear/lib/pu.jar!/
// No entryName specified, hence URL points to a JAR file and
// not to any entry inside it. Ideally this should have been
// file:/tmp/a_ear/lib/pu.jar,
// but containers (e.g.) WebLogic return this kind of URL,
// so we better handle this in our code to improve pluggability.
// Read the entire jar file.
result = new JarFileArchive(rootUrl, conn.getJarFile(), descriptorLocation);
} else if (je.isDirectory()) {
// e.g. jar:file:/tmp/a_ear/b.war!/WEB-INF/classes/
// entryName [je.getName()] is a directory
result = new DirectoryInsideJarURLArchive(rootUrl, descriptorLocation);
} else {
// some URL (e.g.) jar:file:/tmp/a_ear/b.war!/WEB-INF/lib/pu.jar
// entryName [je.getName()] is a file, so treat this URL as a
// URL from which a JAR format InputStream can be obtained.
result = new JarInputStreamURLArchive(rootUrl, descriptorLocation);
}
} else if (isJarInputStream(rootUrl)){
result = new JarInputStreamURLArchive(rootUrl, descriptorLocation);
} else {
result = new URLArchive(rootUrl, descriptorLocation);
}
logger.exiting("ArchiveFactoryImpl", "createArchive", result);
return result;
}
/**
* This method is called for a URL which has neither jar nor file protocol.
* This attempts to find out if we can treat it as a URL from which a JAR
* format InputStream can be obtained.
*/
protected boolean isJarInputStream(URL url) throws IOException {
InputStream in = null;
try {
in = url.openStream();
if (in == null) { // for directories, we may get InputStream as null
return false;
}
JarInputStream jis = null;
try {
jis = new JarInputStream(in);
if (jis.getNextEntry() == null){// if there is no next entry, this jar stream can't be used
return false;
}
return true; // we are successful in creating a Jar format IS
} finally {
if (jis != null){
jis.close();
}
}
} catch (IOException ioe) {
if (in != null) {
in.close();
}
return false;
}
}
}