blob: 72d6b53bd606956b1fb499089c0e203311e8b927 [file] [log] [blame]
package org.eclipse.update.internal.core;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import org.eclipse.core.runtime.*;
import org.eclipse.update.core.*;
/**
* Parse the default feature.xml
*/
public class FeaturePackaged extends Feature {
private JarFile currentOpenJarFile = null;
private URL rootURL;
public static final String JAR_EXTENSION = ".jar";
public static final FilenameFilter filter = new FilenameFilter(){
public boolean accept(File dir, String name){
return name.endsWith(FeaturePackaged.JAR_EXTENSION);
}
};
/**
* @see IFeature#getRootURL()
* In general, the Root URL is the URL of teh Feature
*
* The RootURL is used to calculate relative URL for teh feature
* In case of a file feature, you can just append teh relative path
* to the URL of teh feature
*
* In case of a JAR file, you cannot *just* append the file
* You have to transfrom the URL
*
*/
public URL getRootURL() throws MalformedURLException, IOException, CoreException {
// Extract the JAR file in the TEMP drive
// and return the URL
if (rootURL == null) {
// install the Feature info into the TEMP drive
// extract teh JAR file
SiteFile tempSite = (SiteFile)SiteManager.getTempSite();
InputStream inStream = null;
String[] names = getStorageUnitNames();
if (names != null) {
openFeature();
for (int j = 0; j < names.length; j++) {
if ((inStream = getInputStreamFor(names[j])) != null)
tempSite.storeFeatureInfo(getIdentifier(), names[j], inStream);
}
closeFeature();
}
// get the path to the Feature, which is now pon the file system
// <TempSite>/install/features/<id>_<ver>/
// add '/' as it is a directory
rootURL = UpdateManagerUtils.getURL(tempSite.getURL(),SiteFile.INSTALL_FEATURE_PATH+getIdentifier().toString()+"/",null);
}
return rootURL;
}
/**
* Constructor for DefaultPackagedFeature
*/
public FeaturePackaged(IFeature sourceFeature, ISite targetSite) throws CoreException {
super(sourceFeature, targetSite);
}
/**
* Constructor for DefaultPackagedFeature
*/
public FeaturePackaged(URL url, ISite targetSite) throws CoreException {
super(url, targetSite);
}
/**
* @see AbstractFeature#getContentReferenceToInstall(IPluginEntry[])
*/
public String[] getContentReferenceToInstall(IPluginEntry[] pluginsToInstall) {
String[] names = null;
if (pluginsToInstall != null) {
names = new String[pluginsToInstall.length];
for (int i = 0; i < pluginsToInstall.length; i++) {
names[i] = getArchiveID(pluginsToInstall[i]);
}
}
return names;
}
/**
* @see AbstractFeature#getInputStreamFor(IPluginEntry,String)
*/
public InputStream getInputStreamFor(IPluginEntry pluginEntry, String name) throws CoreException {
URL siteURL = getSite().getURL();
InputStream result = null;
try {
// check if the site.xml had a coded URL for this plugin or if we
// should look in teh default place to find it: <site>+/plugins/+archiveId
String filePath = UpdateManagerUtils.getPath(((Site) getSite()).getURL(getArchiveID(pluginEntry)));
open(filePath);
if (!(new File(filePath)).exists())
throw new IOException("The File:" + filePath + "does not exist.");
ZipEntry entry = currentOpenJarFile.getEntry(name);
result = currentOpenJarFile.getInputStream(entry);
} catch (Exception e) {
String id = UpdateManagerPlugin.getPlugin().getDescriptor().getUniqueIdentifier();
IStatus status = new Status(IStatus.ERROR, id, IStatus.OK, "Error opening :" + name + " in plugin archive:" + pluginEntry.getIdentifier().toString(), e);
throw new CoreException(status);
}
return result;
}
/**
* @see AbstractFeature#getStorageUnitNames(IPluginEntry)
*/
public String[] getStorageUnitNames(IPluginEntry pluginEntry) throws CoreException {
// try to obtain the URL of the JAR file that contains the plugin entry from teh site.xml
// if it doesn't exist, use the default one
URL jarURL = ((Site) getSite()).getURL(getArchiveID(pluginEntry));
String path = UpdateManagerUtils.getPath(jarURL);
String[] result = getJAREntries(path);
return result;
}
/**
* Transfer feature.jar file locally
*/
private void transferLocally() throws CoreException {
// install in DEFAULT PATH for feature
// as we OWN the temp site
try {
String path = UpdateManagerUtils.getPath(getURL());
URL resolvedURL = UpdateManagerUtils.resolveAsLocal(getURL(),path,null);
this.setURL(resolvedURL);
// DEBUG:
if (UpdateManagerPlugin.DEBUG && UpdateManagerPlugin.DEBUG_SHOW_INSTALL) {
UpdateManagerPlugin.getPlugin().debug("the feature on TEMP file is :" + resolvedURL.toExternalForm());
}
} catch (IOException e) {
String id = UpdateManagerPlugin.getPlugin().getDescriptor().getUniqueIdentifier();
IStatus status = new Status(IStatus.ERROR, id, IStatus.OK, "Error transfering feature to TEMP directory", e);
throw new CoreException(status);
}
}
/**
* return the archive ID for a plugin
*/
private String getArchiveID(IPluginEntry entry) {
return Site.DEFAULT_PLUGIN_PATH+entry.getIdentifier().toString() + JAR_EXTENSION;
}
/**
* @see AbstractFeature#getContentReferences()
*/
public String[] getArchives() {
String[] names = new String[getPluginEntryCount()];
IPluginEntry[] entries = getPluginEntries();
for (int i = 0; i < getPluginEntryCount(); i++) {
names[i] = getArchiveID(entries[i]);
}
return names;
}
/**
* @see AbstractFeature#isInstallable()
*/
public boolean isInstallable() {
return true;
}
/**
* @see AbstractFeature#getInputStreamFor(String)
*/
protected InputStream getInputStreamFor(String name) throws CoreException, IOException {
URL siteURL = getSite().getURL();
InputStream result = null;
try {
// ensure the file is local
transferLocally();
// teh feature must have a URL as
//it has been transfered locally
String filePath = UpdateManagerUtils.getPath(getURL());
if (!(new File(filePath)).exists())
throw new IOException("The File:" + filePath + "does not exist.");
open(filePath);
ZipEntry entry = currentOpenJarFile.getEntry(name);
result = currentOpenJarFile.getInputStream(entry);
} catch (IOException e) {
throw new IOException("Error opening :" + name + " in feature archive:" + getURL().toExternalForm() + "\r\n" + e.toString());
}
return result;
}
/**
* @see AbstractFeature#getStorageUnitNames()
*/
protected String[] getStorageUnitNames() throws CoreException {
// make sure the feature archive has been transfered locally
transferLocally();
// get the URL of the feature JAR file
// must exist as we tranfered it locally
String path = UpdateManagerUtils.getPath(getURL());
String[] result = getJAREntries(path);
return result;
}
/**
* return the list of entries in the JAR file
* Do not retrun Directory entries
*
* do not get directories only entry as the directories will
* be created when teh fils will be created
* it was difficult to obtain a correct URL for a Directory inside a JAR
* because of the last '\' in the entry
*/
private String[] getJAREntries(String path) throws CoreException {
String[] result = new String[0];
try {
JarFile jarFile = new JarFile(path);
List list = new ArrayList();
Enumeration enum = jarFile.entries();
int loop = 0;
while (enum.hasMoreElements()) {
ZipEntry nextEntry = (ZipEntry) enum.nextElement();
if (!nextEntry.isDirectory()) {
list.add(nextEntry.getName());
loop++;
}
}
jarFile.close();
// set the result
if (loop > 0 && !list.isEmpty()) {
result = new String[loop];
list.toArray(result);
}
} catch (IOException e) {
String id = UpdateManagerPlugin.getPlugin().getDescriptor().getUniqueIdentifier();
IStatus status = new Status(IStatus.ERROR, id, IStatus.OK, "Error opening JAR file:" + path, e);
throw new CoreException(status);
}
return result;
}
/**
* @see AbstractFeature#close(IPluginEntry)
*/
protected void close(IPluginEntry entry) throws IOException {
if (currentOpenJarFile != null)
currentOpenJarFile.close();
}
/**
* @see AbstractFeature#closeFeature()
*/
public void closeFeature() throws IOException {
if (currentOpenJarFile != null)
currentOpenJarFile.close();
}
/**
* opens a JAR file or returns the one already opened
* if teh path is the same.
*/
protected void open(String filePath) throws IOException {
JarFile newJarFile = new JarFile(filePath);
open(newJarFile);
}
/**
* opens a JAR file or returns the one already opened
* if teh path is the same.
*/
protected void open(JarFile newJarFile) throws IOException {
// are we looking into teh same Jar file
// or shoudl we close the previously opened one and open another one ?
if (currentOpenJarFile != null) {
if (!currentOpenJarFile.getName().equals(newJarFile.getName())) {
currentOpenJarFile.close();
currentOpenJarFile = newJarFile;
} else {
newJarFile.close();
}
} else {
currentOpenJarFile = newJarFile;
}
}
/**
* return the appropriate resource bundle for this feature
* Need to override as opening the JAR keeps it locked
*
* baseclass + "_" + language1 + "_" + country1 + "_" + variant1
* baseclass + "_" + language1 + "_" + country1 + "_" + variant1 + ".properties"
* baseclass + "_" + language1 + "_" + country1
* baseclass + "_" + language1 + "_" + country1 + ".properties"
* baseclass + "_" + language1
* baseclass + "_" + language1 + ".properties"
* baseclass + "_" + language2 + "_" + country2 + "_" + variant2
* baseclass + "_" + language2 + "_" + country2 + "_" + variant2 + ".properties"
* baseclass + "_" + language2 + "_" + country2
* baseclass + "_" + language2 + "_" + country2 + ".properties"
* baseclass + "_" + language2
* baseclass + "_" + language2 + ".properties"
* baseclass
* baseclass + ".properties"
*/
public ResourceBundle getResourceBundle() throws IOException, CoreException {
ResourceBundle result = null;
String[] names = getStorageUnitNames();
String base = FEATURE_FILE;
// retrive names in teh JAR that starts with the basename
// remove FEATURE_XML file
List baseNames = new ArrayList();
for (int i = 0; i < names.length; i++) {
if (names[i].startsWith(base))
baseNames.add(names[i]);
}
baseNames.remove(FEATURE_XML);
// is there any file
if (!baseNames.isEmpty()) {
Locale locale = Locale.getDefault();
String lang1 = locale.getLanguage();
String country1 = locale.getCountry();
String variant1 = locale.getVariant();
String[] attempt =
new String[] {
base + "_" + lang1 + "_" + country1 + "_" + variant1,
base + "_" + lang1 + "_" + country1 + "_" + variant1 + ".properties",
base + "_" + lang1 + "_" + country1,
base + "_" + lang1 + "_" + country1 + ".properties",
base + "_" + lang1,
base + "_" + lang1 + ".properties",
base,
base + ".properties" };
boolean found = false;
int index = 0;
while (!found && index < attempt.length) {
if (baseNames.contains(attempt[index])) {
result = new PropertyResourceBundle(getInputStreamFor(attempt[index]));
found = true;
}
index++;
}
} // baseNames is empty
if (result == null) {
if (UpdateManagerPlugin.DEBUG && UpdateManagerPlugin.DEBUG_SHOW_WARNINGS) {
UpdateManagerPlugin.getPlugin().debug("Cannot find resourceBundle for:" + base + " - " + Locale.getDefault().toString() + ":" + this.getURL().toExternalForm());
}
}
return result;
}
}