blob: e78a474a774b5cd063e2a35bfa5d4e3e2940b5ce [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 1998, 2008 Oracle. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* mkeith - Gemini JPA work (INCUBATION)
*
* This code is being developed under INCUBATION and is not currently included
* in the automated EclipseLink build. The API in this code may change, or
* may never be included in the product. Please provide feedback through mailing
* lists or the bug database.
******************************************************************************/
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.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 javax.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.
*/
private Logger logger;
@SuppressWarnings("deprecation")
public ArchiveFactoryImpl() {
this(Logger.global);
}
public ArchiveFactoryImpl(Logger logger) {
this.logger = logger;
}
public Archive createArchive(URL rootUrl) throws URISyntaxException, IOException {
return createArchive(rootUrl, null);
}
public Archive createArchive(URL rootUrl, URL descriptorUrl) throws URISyntaxException, IOException {
logger.entering("ArchiveFactoryImpl", "createArchive", new Object[]{rootUrl, descriptorUrl});
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);
} 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(new JarFile(f));
}
// mkeith - add bundle archive hook
// TODO Does this work for all OSGi frameworks?
} else if ("bundleresource".equals(protocol)) { // NOI18N
// mkeith - for regular non-embedded descriptors
result = new BundleArchive(rootUrl, descriptorUrl);
} else if ("jar".equals(protocol)) { // NOI18N
JarURLConnection conn = JarURLConnection.class.cast(rootUrl.openConnection());
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 imrove pluggability.
// Read the entire jar file.
result = new JarFileArchive(conn.getJarFile());
} 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);
} 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);
}
} else if (isJarInputStream(rootUrl)){
result = new JarInputStreamURLArchive(rootUrl);
} else {
result = new URLArchive(rootUrl);
}
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.
* @param url
*/
private 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 = new JarInputStream(in);
jis.close();
return true; // we are successful in creating a Jar format IS
} catch (IOException ioe) {
if (in != null) {
in.close();
}
return false;
}
}
}