diff options
author | Dave Stevenson | 2008-02-29 04:36:50 +0000 |
---|---|---|
committer | Dave Stevenson | 2008-02-29 04:36:50 +0000 |
commit | 51a2bfa8b583635605d25876d36bd0cb32514ff0 (patch) | |
tree | 1c8be86c46d93be2fb97b8f5ef1467e44d203e5b /bundles | |
parent | eaeff13c27c437032c4df30fa14e165a9757899a (diff) | |
download | rt.equinox.p2-51a2bfa8b583635605d25876d36bd0cb32514ff0.tar.gz rt.equinox.p2-51a2bfa8b583635605d25876d36bd0cb32514ff0.tar.xz rt.equinox.p2-51a2bfa8b583635605d25876d36bd0cb32514ff0.zip |
Implementation of fragments for localization of bundle manifests.
Diffstat (limited to 'bundles')
8 files changed, 737 insertions, 100 deletions
diff --git a/bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/internal/provisional/p2/directorywatcher/RepositoryListener.java b/bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/internal/provisional/p2/directorywatcher/RepositoryListener.java index 1ae0db781..ce64b6f49 100644 --- a/bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/internal/provisional/p2/directorywatcher/RepositoryListener.java +++ b/bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/internal/provisional/p2/directorywatcher/RepositoryListener.java @@ -306,9 +306,12 @@ public class RepositoryListener extends DirectoryChangeListener { if (featureIUs != null) ius.addAll(Arrays.asList(featureIUs)); } else { - IInstallableUnit bundleIU = generateBundleIU(candidate, props); - if (bundleIU != null) - ius.add(bundleIU); + IInstallableUnit[] bundleIUs = generateBundleIU(candidate, props); + if (bundleIUs != null) { + for (int i = 0; i < bundleIUs.length; i++) { + ius.add(bundleIUs[i]); + } + } } } return (IInstallableUnit[]) ius.toArray(new IInstallableUnit[ius.size()]); @@ -328,15 +331,15 @@ public class RepositoryListener extends DirectoryChangeListener { return new IInstallableUnit[] {featureIU, groupIU}; } - private IInstallableUnit generateBundleIU(File bundleFile, Properties props) { + private IInstallableUnit[] generateBundleIU(File bundleFile, Properties props) { BundleDescription bundleDescription = bundleDescriptionFactory.getBundleDescription(bundleFile); if (bundleDescription == null) return null; IArtifactKey key = MetadataGeneratorHelper.createBundleArtifactKey(bundleDescription.getSymbolicName(), bundleDescription.getVersion().toString()); - IInstallableUnit iu = MetadataGeneratorHelper.createEclipseIU(bundleDescription, (Map) bundleDescription.getUserObject(), false, key, props); - return iu; + IInstallableUnit[] ius = MetadataGeneratorHelper.createEclipseIU(bundleDescription, (Map) bundleDescription.getUserObject(), false, key, props); + return ius; } public IMetadataRepository getMetadataRepository() { diff --git a/bundles/org.eclipse.equinox.p2.metadata.generator/src/org/eclipse/equinox/internal/provisional/p2/metadata/generator/BundleDescriptionFactory.java b/bundles/org.eclipse.equinox.p2.metadata.generator/src/org/eclipse/equinox/internal/provisional/p2/metadata/generator/BundleDescriptionFactory.java index 582167579..33c4c5c92 100644 --- a/bundles/org.eclipse.equinox.p2.metadata.generator/src/org/eclipse/equinox/internal/provisional/p2/metadata/generator/BundleDescriptionFactory.java +++ b/bundles/org.eclipse.equinox.p2.metadata.generator/src/org/eclipse/equinox/internal/provisional/p2/metadata/generator/BundleDescriptionFactory.java @@ -11,8 +11,6 @@ package org.eclipse.equinox.internal.provisional.p2.metadata.generator; import java.io.*; -import java.net.URL; -import java.net.URLConnection; import java.util.*; import java.util.jar.*; import java.util.zip.ZipEntry; @@ -27,7 +25,6 @@ import org.eclipse.osgi.service.resolver.*; import org.eclipse.osgi.util.ManifestElement; import org.eclipse.osgi.util.NLS; import org.osgi.framework.BundleException; -import org.osgi.framework.Constants; public class BundleDescriptionFactory { static final String DIR = "dir"; //$NON-NLS-1$ @@ -38,6 +35,13 @@ public class BundleDescriptionFactory { static String BUNDLE_FILE_KEY = "eclipse.p2.bundle.format"; //$NON-NLS-1$ + // static final String DEFAULT_BUNDLE_LOCALIZATION = "plugin"; //$NON-NLS-1$ + // static final String PROPERTIES_FILE_EXTENSION = ".properties"; //$NON-NLS-1$ + // static final String MANIFEST_LOCALIZATIONS = "eclipse.p2.manifest.localizations"; //$NON-NLS-1$ + // + // static final Locale DEFAULT_LOCALE = new Locale("df", "LT"); //$NON-NLS-1$//$NON-NLS-2$ + // static final Locale PSEUDO_LOCALE = new Locale("zz", "ZZ"); //$NON-NLS-1$//$NON-NLS-2$ + StateObjectFactory factory; State state; @@ -151,60 +155,190 @@ public class BundleDescriptionFactory { return null; manifest.put(BUNDLE_FILE_KEY, bundleLocation.isDirectory() ? DIR : JAR); - localizeManifest(manifest, bundleLocation); + getManifestLocalizations(manifest, bundleLocation); + // localizeManifest(manifest, bundleLocation); return manifest; } - private Properties loadProperties(File bundleLocation, String localizationFile) throws IOException { - Properties result = new Properties(); - InputStream propertyStream = null; - try { - try { - if (bundleLocation.isDirectory()) - propertyStream = new FileInputStream(new File(bundleLocation, localizationFile)); - else { - URLConnection connection = new URL("jar:" + bundleLocation.toURL().toExternalForm() + "!/" + localizationFile).openConnection(); //$NON-NLS-1$ //$NON-NLS-2$ - connection.setUseCaches(false); - propertyStream = connection.getInputStream(); - } - } catch (FileNotFoundException e) { - // if there is no messages file then just return; - return result; - } - result.load(propertyStream); - } finally { - if (propertyStream != null) - propertyStream.close(); - } - return result; - } + // private Properties loadProperties(File bundleLocation, String localizationFile) throws IOException { + // Properties result = new Properties(); + // InputStream propertyStream = null; + // try { + // try { + // if (bundleLocation.isDirectory()) + // propertyStream = new FileInputStream(new File(bundleLocation, localizationFile)); + // else { + // URLConnection connection = new URL("jar:" + bundleLocation.toURL().toExternalForm() + "!/" + localizationFile).openConnection(); //$NON-NLS-1$ //$NON-NLS-2$ + // connection.setUseCaches(false); + // propertyStream = connection.getInputStream(); + // } + // } catch (FileNotFoundException e) { + // // if there is no messages file then just return; + // return result; + // } + // result.load(propertyStream); + // } finally { + // if (propertyStream != null) + // propertyStream.close(); + // } + // return result; + // } - // TODO this is a temporary hack to eagerly bind the translations (i.e., english) strings - // into the manifest values. Eventualy we should stop doing this and have a real NL story for - // metadata. - private void localizeManifest(Dictionary manifest, File bundleLocation) { - String localizationFile = (String) manifest.get(Constants.BUNDLE_LOCALIZATION); - if (localizationFile == null) - localizationFile = "plugin"; //$NON-NLS-1$ - localizationFile += ".properties"; //$NON-NLS-1$ - try { - Properties strings = loadProperties(bundleLocation, localizationFile); - // Walk over the manifest and try to replace all %xxx with the string value in the properties file - for (Enumeration e = manifest.keys(); e.hasMoreElements();) { - String key = (String) e.nextElement(); - String value = (String) manifest.get(key); - if (value.startsWith("%")) { //$NON-NLS-1$ - String newValue = strings.getProperty(value.substring(1)); - if (newValue != null) - manifest.put(key, newValue); - } - } - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } + // Collect the manifest localizations from the bundle directory + // and store them in the manifest. + private void getManifestLocalizations(Dictionary manifest, File bundleLocation) { + // Map localizations; + // Locale defaultLocale = null; // = Locale.ENGLISH; // TODO: get this from GeneratorInfo + // String bundleLocalization = (String) manifest.get(Constants.BUNDLE_LOCALIZATION); + // if (bundleLocalization == null || bundleLocalization.trim().length() == 0) + // bundleLocalization = DEFAULT_BUNDLE_LOCALIZATION; + // + // if ("jar".equalsIgnoreCase(new Path(bundleLocation.getName()).getFileExtension()) && //$NON-NLS-1$ + // bundleLocation.isFile()) { + // localizations = getJarManifestLocalization(bundleLocation, bundleLocalization, manifest, defaultLocale); + // } else { + // localizations = getDirManifestLocalization(bundleLocation, bundleLocalization, manifest, defaultLocale); + // } + // + // if (localizations.size() > 0) { + // manifest.put(MANIFEST_LOCALIZATIONS, localizations); + // } } + // private Map getJarManifestLocalization(File bundleLocation, String bundleLocalization, Dictionary manifest, Locale defaultLocale) { + // ZipFile jarFile = null; + // Map localizations = new HashMap(4); + // try { + // jarFile = new ZipFile(bundleLocation, ZipFile.OPEN_READ); + // for (Enumeration entries = jarFile.entries(); entries.hasMoreElements();) { + // ZipEntry nextEntry = (ZipEntry) entries.nextElement(); + // String nextName = nextEntry.getName(); + // String localeString = getLocaleString(nextName, bundleLocalization); + // + // if (!nextEntry.isDirectory() && localeString != null) { + // Locale nextLocale = getLocale(localeString); + // InputStream stream = null; + // try { + // stream = jarFile.getInputStream(nextEntry); + // Properties properties = new Properties(); + // properties.load(stream); + // Properties localizedStrings = getLocalizedProperties(manifest, properties); + // if (localizedStrings.size() > 0) { + // localizations.put(nextLocale, localizedStrings); + // if (DEFAULT_LOCALE.equals(nextLocale) && defaultLocale != null) { + // localizations.put(nextLocale, localizedStrings); + // } + // } + // } finally { + // if (stream != null) + // stream.close(); + // } + // } + // } + // } catch (IOException ioe) { + // ioe.printStackTrace(); + // } finally { + // if (jarFile != null) { + // try { + // jarFile.close(); + // } catch (IOException ioe) { + // // do nothing + // } + // } + // } + // + // return localizations; + // } + // + // private Map getDirManifestLocalization(File bundleLocation, String bundleLocalization, Dictionary manifest, Locale defaultLocale) { + // File localizationPath = new File(bundleLocation, bundleLocalization); + // File localizationDir = localizationPath.getParentFile(); + // String localizationFile = localizationPath.getName(); + // String[] localizationFiles = localizationDir.list(new LocalizationFileFilter(localizationFile)); + // + // HashMap localizations = null; + // + // if (localizationFiles != null) { + // localizations = new HashMap(localizationFiles.length); + // for (int i = 0; i < localizationFiles.length; i++) { + // String nextFile = localizationFiles[i]; + // Locale nextLocale = getLocale(getLocaleString(nextFile, localizationFile)); + // + // try { + // Properties properties = loadProperties(bundleLocation, nextFile); + // Properties localizedStrings = getLocalizedProperties(manifest, properties); + // if (localizedStrings.size() > 0) { + // localizations.put(nextLocale, localizedStrings); + // if (DEFAULT_LOCALE.equals(nextLocale) && defaultLocale != null) { + // localizations.put(nextLocale, localizedStrings); + // } + // } + // } catch (IOException ioe) { + // ioe.printStackTrace(); + // } + // } + // } + // + // return localizations; + // } + + // private class LocalizationFileFilter implements FilenameFilter { + // + // String filenamePrefix; + // + // public LocalizationFileFilter(String filenamePrefix) { + // this.filenamePrefix = filenamePrefix; + // } + // + // /* (non-Javadoc) + // * @see java.io.FilenameFilter#accept(java.io.File, java.lang.String) + // */ + // public boolean accept(File directory, String filename) { + // return (getLocaleString(filename, filenamePrefix) != null ? true : false); + // } + // } + + // static public String getLocaleString(String filename, String filenamePrefix) { + // String localeString = null; + // if (filename.startsWith(filenamePrefix) && filename.endsWith(PROPERTIES_FILE_EXTENSION)) { + // if (filename.length() > filenamePrefix.length() + PROPERTIES_FILE_EXTENSION.length()) { + // localeString = filename.substring(filenamePrefix.length() + 1, filename.length() - PROPERTIES_FILE_EXTENSION.length()); + // } else { + // localeString = ""; //$NON-NLS-1$ + // } + // } + // return localeString; + // } + + // static private Locale getLocale(String localeString) { + // Locale locale = DEFAULT_LOCALE; + // if (localeString.length() == 5 && localeString.indexOf('_') == 2) { + // locale = new Locale(localeString.substring(0, 2), localeString.substring(3, 5)); + // } else if (localeString.length() == 2) { + // locale = new Locale(localeString.substring(0, 2)); + // } + // return locale; + // } + // + // static private Properties getLocalizedProperties(Dictionary manifest, Properties properties) { + // // Walk over the manifest and find all %xxx with the string value + // // in the properties file and copy them to the localized properties. + // Properties localizedProperties = new Properties(); + // for (Enumeration e = manifest.keys(); e.hasMoreElements();) { + // String key = (String) e.nextElement(); + // Object value = manifest.get(key); + // if (value instanceof String) { + // String stringValue = (String) value; + // if (stringValue.startsWith("%")) { //$NON-NLS-1$ + // String newValue = properties.getProperty(stringValue.substring(1)); + // if (newValue != null) + // localizedProperties.put(key, newValue); + // } + // } + // } + // return localizedProperties; + // } + private Properties manifestToProperties(Attributes attributes) { Properties result = new Properties(); for (Iterator i = attributes.keySet().iterator(); i.hasNext();) { diff --git a/bundles/org.eclipse.equinox.p2.metadata.generator/src/org/eclipse/equinox/internal/provisional/p2/metadata/generator/Generator.java b/bundles/org.eclipse.equinox.p2.metadata.generator/src/org/eclipse/equinox/internal/provisional/p2/metadata/generator/Generator.java index ad5ec421c..dfb49fbbd 100644 --- a/bundles/org.eclipse.equinox.p2.metadata.generator/src/org/eclipse/equinox/internal/provisional/p2/metadata/generator/Generator.java +++ b/bundles/org.eclipse.equinox.p2.metadata.generator/src/org/eclipse/equinox/internal/provisional/p2/metadata/generator/Generator.java @@ -93,6 +93,8 @@ public class Generator { private static final String ORG_ECLIPSE_UPDATE_CONFIGURATOR = "org.eclipse.update.configurator"; //$NON-NLS-1$ private static final String ORG_ECLIPSE_EQUINOX_LAUNCHER = "org.eclipse.equinox.launcher"; //$NON-NLS-1$ + static final String DEFAULT_BUNDLE_LOCALIZATION = "plugin"; //$NON-NLS-1$ + private final IGeneratorInfo info; private GeneratorResult incrementalResult = null; @@ -305,32 +307,86 @@ public class Generator { } protected void generateBundleIUs(BundleDescription[] bundles, GeneratorResult result, IArtifactRepository destination) { - for (int i = 0; i < bundles.length; i++) { - BundleDescription bd = bundles[i]; - // A bundle may be null if the associated plug-in does not have a manifest file - - // for example, org.eclipse.jdt.launching.j9 - if (bd != null && bd.getSymbolicName() != null && bd.getVersion() != null) { - String format = (String) ((Dictionary) bd.getUserObject()).get(BundleDescriptionFactory.BUNDLE_FILE_KEY); - boolean isDir = format.equals(BundleDescriptionFactory.DIR) ? true : false; - IArtifactKey key = MetadataGeneratorHelper.createBundleArtifactKey(bd.getSymbolicName(), bd.getVersion().toString()); - IArtifactDescriptor ad = MetadataGeneratorHelper.createArtifactDescriptor(key, new File(bd.getLocation()), true, false); - if (isDir) - publishArtifact(ad, new File(bd.getLocation()).listFiles(), destination, false); - else - publishArtifact(ad, new File[] {new File(bd.getLocation())}, destination, true); - if (info.reuseExistingPack200Files() && !info.publishArtifacts()) { - File packFile = new Path(bd.getLocation()).addFileExtension("pack.gz").toFile(); //$NON-NLS-1$ - if (packFile.exists()) { - IArtifactDescriptor ad200 = MetadataGeneratorHelper.createPack200ArtifactDescriptor(key, packFile, ad.getProperty(IArtifactDescriptor.ARTIFACT_SIZE)); - publishArtifact(ad200, new File[] {packFile}, destination, true); + // Computing the path for localized property files in a NL fragment bundle + // requires the BUNDLE_LOCALIZATION property from the manifest of the host bundle, + // so a first pass is done over all the bundles to cache this value as well as the tags + // from the manifest for the localizable properties. + final int CACHE_PHASE = 0; + final int GENERATE_PHASE = 1; + final int BUNDLE_LOCALIZATION_INDEX = MetadataGeneratorHelper.BUNDLE_LOCALIZATION_INDEX; + Map bundleLocalizationMap = new HashMap(bundles.length); + Set localizationIUs = new HashSet(32); + for (int phase = CACHE_PHASE; phase <= GENERATE_PHASE; phase++) { + for (int i = 0; i < bundles.length; i++) { + BundleDescription bd = bundles[i]; + // A bundle may be null if the associated plug-in does not have a manifest file - + // for example, org.eclipse.jdt.launching.j9 + if (bd != null && bd.getSymbolicName() != null && bd.getVersion() != null) { + Map bundleManifest = (Map) bd.getUserObject(); + + if (phase == CACHE_PHASE) { + if (bundleManifest != null) { + String[] cachedValues = MetadataGeneratorHelper.getManifestCachedValues(bundleManifest); + bundleLocalizationMap.put(makeSimpleKey(bd), cachedValues); + } + } else { + String format = (String) (bundleManifest).get(BundleDescriptionFactory.BUNDLE_FILE_KEY); + boolean isDir = (format != null && format.equals(BundleDescriptionFactory.DIR) ? true : false); + + IArtifactKey key = MetadataGeneratorHelper.createBundleArtifactKey(bd.getSymbolicName(), bd.getVersion().toString()); + IArtifactDescriptor ad = MetadataGeneratorHelper.createArtifactDescriptor(key, new File(bd.getLocation()), true, false); + if (isDir) + publishArtifact(ad, new File(bd.getLocation()).listFiles(), destination, false); + else + publishArtifact(ad, new File[] {new File(bd.getLocation())}, destination, true); + if (info.reuseExistingPack200Files() && !info.publishArtifacts()) { + File packFile = new Path(bd.getLocation()).addFileExtension("pack.gz").toFile(); //$NON-NLS-1$ + if (packFile.exists()) { + IArtifactDescriptor ad200 = MetadataGeneratorHelper.createPack200ArtifactDescriptor(key, packFile, ad.getProperty(IArtifactDescriptor.ARTIFACT_SIZE)); + publishArtifact(ad200, new File[] {packFile}, destination, true); + } + } + + IInstallableUnit bundleIU = MetadataGeneratorHelper.createBundleIU(bd, bundleManifest, isDir, key, localizationIUs); + + if (isFragment(bd)) { + // TODO: Can NL fragments be multi-host? What special handling + // is required for multi-host fragments in general? + String hostId = bd.getHost().getName(); + String hostKey = makeSimpleKey(hostId); + String[] cachedValues = (String[]) bundleLocalizationMap.get(hostKey); + + if (cachedValues != null) { + MetadataGeneratorHelper.createHostLocalizationFragments(bd, hostId, cachedValues, localizationIUs); + } + } + + result.rootIUs.add(bundleIU); + result.nonRootIUs.addAll(localizationIUs); + localizationIUs.clear(); } } - IInstallableUnit iu = MetadataGeneratorHelper.createBundleIU(bd, (Map) bd.getUserObject(), isDir, key); - result.rootIUs.add(iu); } } } + private static boolean isFragment(BundleDescription bd) { + return (bd.getHost() != null ? true : false); + } + + private static String makeSimpleKey(BundleDescription bd) { + // TODO: can't use the bundle version in the key for the BundleLocalization + // property map since the host specification for a fragment has a + // version range, not a version. Hence, this mechanism for finding + // manifest localization property files may break under changes + // to the BundleLocalization property of a bundle. + return makeSimpleKey(bd.getSymbolicName() /*, bd.getVersion() */); + } + + private static String makeSimpleKey(String id /*, Version version */) { + return id; // + '_' + version.toString(); + } + /** * Generates IUs corresponding to update site categories. * @param categoriesToFeatures Map of SiteCategory ->Set (Feature IUs in that category). diff --git a/bundles/org.eclipse.equinox.p2.metadata.generator/src/org/eclipse/equinox/internal/provisional/p2/metadata/generator/MetadataGeneratorHelper.java b/bundles/org.eclipse.equinox.p2.metadata.generator/src/org/eclipse/equinox/internal/provisional/p2/metadata/generator/MetadataGeneratorHelper.java index 247806f79..53b7d9a69 100644 --- a/bundles/org.eclipse.equinox.p2.metadata.generator/src/org/eclipse/equinox/internal/provisional/p2/metadata/generator/MetadataGeneratorHelper.java +++ b/bundles/org.eclipse.equinox.p2.metadata.generator/src/org/eclipse/equinox/internal/provisional/p2/metadata/generator/MetadataGeneratorHelper.java @@ -12,7 +12,12 @@ package org.eclipse.equinox.internal.provisional.p2.metadata.generator; import java.io.*; +import java.net.URL; +import java.net.URLConnection; import java.util.*; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import org.eclipse.core.runtime.Path; import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper; import org.eclipse.equinox.internal.p2.metadata.ArtifactKey; import org.eclipse.equinox.internal.p2.metadata.InstallableUnit; @@ -57,6 +62,17 @@ public class MetadataGeneratorHelper { */ public static final String TYPE_ECLIPSE_SOURCE = "source"; //$NON-NLS-1$ + /** + * A capability name in the {@link #NAMESPACE_ECLIPSE_TYPE} namespace + * representing localized manifest properties + * @see RequiredCapability#getName() + */ + public static final String TYPE_ECLIPSE_MANIFEST_LOCALIZATION = "manifest.localization"; //$NON-NLS-1$ + + // Only certain properties in the bundle manifest are assumed to be localized. + public static final String[] BUNDLE_LOCALIZED_PROPERTIES = {Constants.BUNDLE_NAME, Constants.BUNDLE_DESCRIPTION, Constants.BUNDLE_VENDOR, Constants.BUNDLE_CONTACTADDRESS, Constants.BUNDLE_DOCURL, Constants.BUNDLE_UPDATELOCATION}; + public static final int BUNDLE_LOCALIZATION_INDEX = BUNDLE_LOCALIZED_PROPERTIES.length; + private static final String[] BUNDLE_IU_PROPERTY_MAP = {Constants.BUNDLE_NAME, IInstallableUnit.PROP_NAME, Constants.BUNDLE_DESCRIPTION, IInstallableUnit.PROP_DESCRIPTION, Constants.BUNDLE_VENDOR, IInstallableUnit.PROP_PROVIDER, Constants.BUNDLE_CONTACTADDRESS, IInstallableUnit.PROP_CONTACT, Constants.BUNDLE_DOCURL, IInstallableUnit.PROP_DOC_URL}; private static final String CAPABILITY_NS_JAVA_PACKAGE = "java.package"; //$NON-NLS-1$ @@ -90,6 +106,14 @@ public class MetadataGeneratorHelper { public static final ProvidedCapability BUNDLE_CAPABILITY = MetadataFactory.createProvidedCapability(NAMESPACE_ECLIPSE_TYPE, TYPE_ECLIPSE_BUNDLE, new Version(1, 0, 0)); public static final ProvidedCapability FEATURE_CAPABILITY = MetadataFactory.createProvidedCapability(NAMESPACE_ECLIPSE_TYPE, TYPE_ECLIPSE_FEATURE, new Version(1, 0, 0)); public static final ProvidedCapability SOURCE_BUNDLE_CAPABILITY = MetadataFactory.createProvidedCapability(NAMESPACE_ECLIPSE_TYPE, TYPE_ECLIPSE_SOURCE, new Version(1, 0, 0)); + public static final ProvidedCapability MANIFEST_LOCALIZATION_CAPABILITY = MetadataFactory.createProvidedCapability(NAMESPACE_ECLIPSE_TYPE, TYPE_ECLIPSE_MANIFEST_LOCALIZATION, new Version(1, 0, 0)); + + static final String DEFAULT_BUNDLE_LOCALIZATION = "plugin"; //$NON-NLS-1$ + static final String PROPERTIES_FILE_EXTENSION = ".properties"; //$NON-NLS-1$ + static final String MANIFEST_LOCALIZATIONS = "eclipse.p2.manifest.localizations"; //$NON-NLS-1$ + + static final Locale DEFAULT_LOCALE = new Locale("df", "LT"); //$NON-NLS-1$//$NON-NLS-2$ + static final Locale PSEUDO_LOCALE = new Locale("zz", "ZZ"); //$NON-NLS-1$//$NON-NLS-2$ public static IArtifactDescriptor createArtifactDescriptor(IArtifactKey key, File pathOnDisk, boolean asIs, boolean recur) { //TODO this size calculation is bogus @@ -149,6 +173,20 @@ public class MetadataGeneratorHelper { return MetadataFactory.createInstallableUnit(cu); } + public static IInstallableUnit createBundleIU(BundleDescription bd, Map manifest, boolean isFolderPlugin, IArtifactKey key, Set localizationIUs) { + IInstallableUnit bundleIU = createBundleIU(bd, manifest, isFolderPlugin, key); + + String bundleLocalization = (String) manifest.get(Constants.BUNDLE_LOCALIZATION); + if (bundleLocalization == null) { + bundleLocalization = DEFAULT_BUNDLE_LOCALIZATION; + } + Map manifestLocalizations = getManifestLocalizations(manifest, new File(bd.getLocation())); + if (manifestLocalizations != null) { + localizationIUs.addAll(createLocalizationFragmentsForBundle(bd, manifestLocalizations)); + } + return bundleIU; + } + public static IInstallableUnit createBundleIU(BundleDescription bd, Map manifest, boolean isFolderPlugin, IArtifactKey key) { boolean isBinaryBundle = true; if (manifest != null && manifest.containsKey("Eclipse-SourceBundle")) { //$NON-NLS-1$ @@ -175,7 +213,7 @@ public class MetadataGeneratorHelper { for (int j = 0; j < requiredBundles.length; j++) reqsDeps.add(MetadataFactory.createRequiredCapability(CAPABILITY_NS_OSGI_BUNDLE, requiredBundles[j].getName(), requiredBundles[j].getVersionRange() == VersionRange.emptyRange ? null : requiredBundles[j].getVersionRange(), null, requiredBundles[j].isOptional(), false)); - //Process the import package + // Process the import packages ImportPackageSpecification osgiImports[] = bd.getImportPackages(); for (int i = 0; i < osgiImports.length; i++) { // TODO we need to sort out how we want to handle wild-carded dynamic imports - for now we ignore them @@ -191,12 +229,12 @@ public class MetadataGeneratorHelper { } iu.setRequiredCapabilities((RequiredCapability[]) reqsDeps.toArray(new RequiredCapability[reqsDeps.size()])); - // Create Set of provided capabilities + // Create set of provided capabilities ArrayList providedCapabilities = new ArrayList(); providedCapabilities.add(createSelfCapability(bd.getSymbolicName(), bd.getVersion())); providedCapabilities.add(MetadataFactory.createProvidedCapability(CAPABILITY_NS_OSGI_BUNDLE, bd.getSymbolicName(), bd.getVersion())); - //Process the export package + // Process the export package ExportPackageDescription exports[] = bd.getExportPackages(); for (int i = 0; i < exports.length; i++) { //TODO make sure that we support all the refinement on the exports @@ -216,16 +254,16 @@ public class MetadataGeneratorHelper { iu.setTouchpointType(TOUCHPOINT_OSGI); - // Set IU properties from the manifest header attributes - // TODO The values of the attributes may be localized. Metadata generation - // should construct property files for the IU based on the bundle/plug-in - // property files in whatever locales are provided. + // Set certain properties from the manifest header attributes as IU properties. + // The values of these attributes may be localized (strings starting with '%') + // with the translated values appearing in the localization IU fragments + // associated with the bundle IU. if (manifest != null) { int i = 0; while (i < BUNDLE_IU_PROPERTY_MAP.length) { if (manifest.containsKey(BUNDLE_IU_PROPERTY_MAP[i])) { String value = (String) manifest.get(BUNDLE_IU_PROPERTY_MAP[i]); - if (value != null) { + if (value != null && value.length() > 0) { iu.setProperty(BUNDLE_IU_PROPERTY_MAP[i + 1], value); } } @@ -240,9 +278,110 @@ public class MetadataGeneratorHelper { touchpointData.put("zipped", "true"); //$NON-NLS-1$ //$NON-NLS-2$ touchpointData.put("manifest", toManifestString(manifest)); //$NON-NLS-1$ iu.addTouchpointData(MetadataFactory.createTouchpointData(touchpointData)); + return MetadataFactory.createInstallableUnit(iu); } + private static List createLocalizationFragmentsForBundle(BundleDescription bd, Map manifestLocalizations) { + List localizationFragments = new ArrayList(manifestLocalizations.size()); + for (Iterator iter = manifestLocalizations.keySet().iterator(); iter.hasNext();) { + Locale locale = (Locale) iter.next(); + Properties localizedStrings = (Properties) manifestLocalizations.get(locale); + IInstallableUnitFragment nextLocaleFragment = createLocalizationFragmentOfBundle(bd, locale, localizedStrings); + localizationFragments.add(nextLocaleFragment); + } + return localizationFragments; + } + + /* + * @param bd + * @param locale + * @param localizedStrings + * @return installableUnitFragment + */ + private static IInstallableUnitFragment createLocalizationFragmentOfBundle(BundleDescription bd, Locale locale, Properties localizedStrings) { + InstallableUnitFragmentDescription fragment = new MetadataFactory.InstallableUnitFragmentDescription(); + String fragmentId = makeLocalizationFragmentId(bd.getSymbolicName(), locale); + fragment.setId(fragmentId); + fragment.setVersion(bd.getVersion()); + + RequiredCapability[] hostReqs = new RequiredCapability[] {MetadataFactory.createRequiredCapability(NAMESPACE_ECLIPSE_TYPE, bd.getSymbolicName(), new VersionRange(bd.getVersion(), true, bd.getVersion(), true), null, false, false)}; + fragment.setHost(hostReqs); + + fragment.setSingleton(true); + + Enumeration propertyKeys = localizedStrings.propertyNames(); + while (propertyKeys.hasMoreElements()) { + String nextKey = (String) propertyKeys.nextElement(); + fragment.setProperty(nextKey, localizedStrings.getProperty(nextKey)); + } + // TODO: do we need any capabilities? + // Create set of provided capabilities It's just a tag indicating a localization fragment. + ArrayList providedCapabilities = new ArrayList(1); + providedCapabilities.add(MANIFEST_LOCALIZATION_CAPABILITY); + fragment.setCapabilities((ProvidedCapability[]) providedCapabilities.toArray(new ProvidedCapability[providedCapabilities.size()])); + + return MetadataFactory.createInstallableUnitFragment(fragment); + } + + public static void createHostLocalizationFragments(BundleDescription bd, String hostId, String[] hostBundleManifestValues, Set localizationIUs) { + Map hostLocalizations = getHostLocalizations(new File(bd.getLocation()), hostBundleManifestValues); + + for (Iterator iter = hostLocalizations.keySet().iterator(); iter.hasNext();) { + Locale locale = (Locale) iter.next(); + Properties localizedStrings = (Properties) hostLocalizations.get(locale); + IInstallableUnitFragment nextLocaleFragment = createLocalizationFragmentOfHost(hostId, hostBundleManifestValues, bd, locale, localizedStrings); + localizationIUs.add(nextLocaleFragment); + } + } + + /* + * @param hostId + * @param bd + * @param locale + * @param localizedStrings + * @return installableUnitFragment + */ + private static IInstallableUnitFragment createLocalizationFragmentOfHost(String hostId, String[] hostManifestValues, BundleDescription bd, Locale locale, Properties localizedStrings) { + InstallableUnitFragmentDescription fragment = new MetadataFactory.InstallableUnitFragmentDescription(); + HostSpecification hostSpec = bd.getHost(); + String fragmentId = makeLocalizationFragmentId(hostId, locale); + fragment.setId(fragmentId); + fragment.setVersion(bd.getVersion()); // TODO: is this a meaningful version? + + RequiredCapability[] hostReqs = new RequiredCapability[] {MetadataFactory.createRequiredCapability(NAMESPACE_ECLIPSE_TYPE, hostSpec.getName(), hostSpec.getVersionRange(), null, false, false)}; + fragment.setHost(hostReqs); + + fragment.setSingleton(true); + + for (int i = 0; i < BUNDLE_LOCALIZED_PROPERTIES.length; i++) { + String nextKey = hostManifestValues[i]; + String localizedValue = null; + if (nextKey != null && (localizedValue = localizedStrings.getProperty(nextKey)) != null) { + fragment.setProperty(nextKey, localizedValue); + } + } + // TODO: do we need any capabilities? It's just a tag indicating a localization fragment. + // Create set of provided capabilities + ArrayList providedCapabilities = new ArrayList(1); + providedCapabilities.add(MANIFEST_LOCALIZATION_CAPABILITY); + fragment.setCapabilities((ProvidedCapability[]) providedCapabilities.toArray(new ProvidedCapability[providedCapabilities.size()])); + + return MetadataFactory.createInstallableUnitFragment(fragment); + } + + /** + * @param id + * @param locale + * @return the id for the fragment contain the localized properties + * for the manifest of the bundle with the given id + * in the given locale. + */ + private static String makeLocalizationFragmentId(String id, Locale locale) { + String localeString = (!DEFAULT_LOCALE.equals(locale) ? '_' + locale.toString() : ""); //$NON-NLS-1$ + return id + "_manifest" + localeString + "_properties"; //$NON-NLS-1$ //$NON-NLS-2$ + } + /** * Creates an IU corresponding to an update site category * @param category The category descriptor @@ -377,16 +516,41 @@ public class MetadataGeneratorHelper { return MetadataFactory.createInstallableUnit(cu); } - // TODO: TEMPORARY - We should figure out if we want to expose something like InstallableUnitDescription - public static IInstallableUnit createEclipseIU(BundleDescription bd, Map manifest, boolean isFolderPlugin, IArtifactKey key, Properties extraProperties) { - InstallableUnit iu = (InstallableUnit) createBundleIU(bd, manifest, isFolderPlugin, key); + private static void addExtraProperties(IInstallableUnit iiu, Properties extraProperties) { + if (iiu instanceof InstallableUnit) { + InstallableUnit iu = (InstallableUnit) iiu; - Enumeration e = extraProperties.propertyNames(); - while (e.hasMoreElements()) { - String name = (String) e.nextElement(); - iu.setProperty(name, extraProperties.getProperty(name)); + for (Enumeration e = extraProperties.propertyNames(); e.hasMoreElements();) { + String name = (String) e.nextElement(); + iu.setProperty(name, extraProperties.getProperty(name)); + } } - return iu; + } + + public static IInstallableUnit[] createEclipseIU(BundleDescription bd, Map manifest, boolean isFolderPlugin, IArtifactKey key, Properties extraProperties) { + ArrayList iusCreated = new ArrayList(4); + + IInstallableUnit iu = createBundleIU(bd, manifest, isFolderPlugin, key); + addExtraProperties(iu, extraProperties); + iusCreated.add(iu); + + String bundleLocalization = null; + if (bd.getHost() == null) // not a fragment + bundleLocalization = (String) manifest.get(Constants.BUNDLE_LOCALIZATION); + if (bundleLocalization == null) + bundleLocalization = DEFAULT_BUNDLE_LOCALIZATION; + + Map manifestLocalizations = getManifestLocalizations(manifest, new File(bd.getLocation())); + + if (manifestLocalizations != null) { + List localizationFragments = createLocalizationFragmentsForBundle(bd, manifestLocalizations); + for (Iterator iter = localizationFragments.iterator(); iter.hasNext();) { + addExtraProperties((IInstallableUnit) iter.next(), extraProperties); + } + iusCreated.addAll(localizationFragments); + } + + return (IInstallableUnit[]) (iusCreated.toArray(new IInstallableUnit[iusCreated.size()])); } public static IArtifactKey createFeatureArtifactKey(String fsn, String version) { @@ -777,4 +941,207 @@ public class MetadataGeneratorHelper { return result.toString(); } + // Return a map from locale to property set for the manifest localizations + // from the given bundle directory and given bundle localization path/name + // manifest property value. + private static Map getManifestLocalizations(Map manifest, File bundleLocation) { + Map localizations; + Locale defaultLocale = null; // = Locale.ENGLISH; // TODO: get this from GeneratorInfo + String[] bundleManifestValues = getManifestCachedValues(manifest); + String bundleLocalization = bundleManifestValues[BUNDLE_LOCALIZATION_INDEX]; + + if ("jar".equalsIgnoreCase(new Path(bundleLocation.getName()).getFileExtension()) && //$NON-NLS-1$ + bundleLocation.isFile()) { + localizations = getJarManifestLocalization(bundleLocation, bundleLocalization, defaultLocale, bundleManifestValues); + } else { + localizations = getDirManifestLocalization(bundleLocation, bundleLocalization, defaultLocale, bundleManifestValues); + } + + return localizations; + } + + public static String[] getManifestCachedValues(Map manifest) { + String[] cachedValues = new String[BUNDLE_LOCALIZED_PROPERTIES.length + 1]; + for (int j = 0; j < MetadataGeneratorHelper.BUNDLE_LOCALIZED_PROPERTIES.length; j++) { + String value = (String) manifest.get(BUNDLE_LOCALIZED_PROPERTIES[j]); + if (value != null && value.length() > 1 && value.charAt(0) == '%') { + cachedValues[j] = value.substring(1); + } + } + String localizationFile = (String) manifest.get(org.osgi.framework.Constants.BUNDLE_LOCALIZATION); + cachedValues[BUNDLE_LOCALIZATION_INDEX] = (localizationFile != null ? localizationFile : DEFAULT_BUNDLE_LOCALIZATION); + return cachedValues; + } + + // Return a map from locale to property set for the manifest localizations + // from the given bundle directory and given bundle localization path/name + // manifest property value. + public static Map getHostLocalizations(File bundleLocation, String[] hostBundleManifestValues) { + Map localizations; + Locale defaultLocale = null; // = Locale.ENGLISH; // TODO: get this from GeneratorInfo + String hostBundleLocalization = hostBundleManifestValues[BUNDLE_LOCALIZATION_INDEX]; + + if ("jar".equalsIgnoreCase(new Path(bundleLocation.getName()).getFileExtension()) && //$NON-NLS-1$ + bundleLocation.isFile()) { + localizations = getJarManifestLocalization(bundleLocation, hostBundleLocalization, defaultLocale, hostBundleManifestValues); + } else { + localizations = getDirManifestLocalization(bundleLocation, hostBundleLocalization, defaultLocale, hostBundleManifestValues); + } + + return localizations; + } + + private static Map getJarManifestLocalization(File bundleLocation, String bundleLocalization, Locale defaultLocale, String[] bundleManifestValues) { + ZipFile jarFile = null; + Map localizations = new HashMap(4); + try { + jarFile = new ZipFile(bundleLocation, ZipFile.OPEN_READ); + for (Enumeration entries = jarFile.entries(); entries.hasMoreElements();) { + ZipEntry nextEntry = (ZipEntry) entries.nextElement(); + String nextName = nextEntry.getName(); + String localeString = getLocaleString(nextName, bundleLocalization); + + if (!nextEntry.isDirectory() && localeString != null) { + Locale nextLocale = getLocale(localeString); + InputStream stream = null; + try { + stream = jarFile.getInputStream(nextEntry); + Properties properties = new Properties(); + properties.load(stream); + Properties localizedStrings = getLocalizedProperties(bundleManifestValues, properties); + if (localizedStrings.size() > 0) { + localizations.put(nextLocale, localizedStrings); + if (DEFAULT_LOCALE.equals(nextLocale) && defaultLocale != null) { + localizations.put(nextLocale, localizedStrings); + } + } + } finally { + if (stream != null) + stream.close(); + } + } + } + } catch (IOException ioe) { + ioe.printStackTrace(); + } finally { + if (jarFile != null) { + try { + jarFile.close(); + } catch (IOException ioe) { + // do nothing + } + } + } + + return localizations; + } + + private static Map getDirManifestLocalization(File bundleLocation, String bundleLocalization, Locale defaultLocale, String[] hostBundleManifestValues) { + File localizationPath = new File(bundleLocation, bundleLocalization); + File localizationDir = localizationPath.getParentFile(); + final String localizationFile = localizationPath.getName(); + MetadataGeneratorHelper foo = new MetadataGeneratorHelper(); + String[] localizationFiles = localizationDir.list(foo.new LocalizationFileFilter() { + public boolean accept(File directory, String filename) { + return (getLocaleString(filename, localizationFile) != null ? true : false); + } + }); + + HashMap localizations = null; + + if (localizationFiles != null) { + localizations = new HashMap(localizationFiles.length); + for (int i = 0; i < localizationFiles.length; i++) { + String nextFile = localizationFiles[i]; + Locale nextLocale = getLocale(getLocaleString(nextFile, localizationFile)); + + try { + Properties properties = loadProperties(bundleLocation, nextFile); + Properties localizedStrings = getLocalizedProperties(hostBundleManifestValues, properties); + if (localizedStrings.size() > 0) { + localizations.put(nextLocale, localizedStrings); + if (DEFAULT_LOCALE.equals(nextLocale) && defaultLocale != null) { + localizations.put(nextLocale, localizedStrings); + } + } + } catch (IOException ioe) { + ioe.printStackTrace(); + } + } + } + + return localizations; + } + + private abstract class LocalizationFileFilter implements FilenameFilter { + + public LocalizationFileFilter() { + // Nothing to do + } + + /* (non-Javadoc) + * @see java.io.FilenameFilter#accept(java.io.File, java.lang.String) + */ + public abstract boolean accept(File directory, String filename); + } + + static public String getLocaleString(String filename, String filenamePrefix) { + String localeString = null; + if (filename.startsWith(filenamePrefix) && filename.endsWith(PROPERTIES_FILE_EXTENSION)) { + if (filename.length() > filenamePrefix.length() + PROPERTIES_FILE_EXTENSION.length()) { + localeString = filename.substring(filenamePrefix.length() + 1, filename.length() - PROPERTIES_FILE_EXTENSION.length()); + } else { + localeString = ""; //$NON-NLS-1$ + } + } + return localeString; + } + + private static Properties loadProperties(File bundleLocation, String localizationFile) throws IOException { + Properties result = new Properties(); + InputStream propertyStream = null; + try { + try { + if (bundleLocation.isDirectory()) + propertyStream = new FileInputStream(new File(bundleLocation, localizationFile)); + else { + URLConnection connection = new URL("jar:" + bundleLocation.toURL().toExternalForm() + "!/" + localizationFile).openConnection(); //$NON-NLS-1$ //$NON-NLS-2$ + connection.setUseCaches(false); + propertyStream = connection.getInputStream(); + } + } catch (FileNotFoundException e) { + // if there is no messages file then just return; + return result; + } + result.load(propertyStream); + } finally { + if (propertyStream != null) + propertyStream.close(); + } + return result; + } + + static private Locale getLocale(String localeString) { + Locale locale = DEFAULT_LOCALE; + if (localeString.length() == 5 && localeString.indexOf('_') == 2) { + locale = new Locale(localeString.substring(0, 2), localeString.substring(3, 5)); + } else if (localeString.length() == 2) { + locale = new Locale(localeString.substring(0, 2)); + } + return locale; + } + + static private Properties getLocalizedProperties(String[] bundleManifestKeys, Properties properties) { + Properties localizedProperties = new Properties(); + for (int i = 0; i < BUNDLE_LOCALIZED_PROPERTIES.length; i++) { + String key = bundleManifestKeys[i]; + if (key != null) { + String localizedValue = properties.getProperty(key); + if (localizedValue != null) + localizedProperties.put(key, localizedValue); + } + } + return localizedProperties; + } + } diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/directorywatcher/RepositoryListenerTest.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/directorywatcher/RepositoryListenerTest.java index a3a692010..e7c36ac55 100644 --- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/directorywatcher/RepositoryListenerTest.java +++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/directorywatcher/RepositoryListenerTest.java @@ -95,14 +95,14 @@ public class RepositoryListenerTest extends AbstractProvisioningTest { assertTrue("2.3", repo.getArtifactFile(keys[i]).toString().startsWith(folder.getAbsolutePath().toString())); } - assertEquals("3.0", 2, getInstallableUnits(listener).length); + assertEquals("3.0", 4, getInstallableUnits(listener).length); assertEquals("3.1", 2, listener.getArtifactRepository().getArtifactKeys().length); watcher = new DirectoryWatcher(props, TestActivator.getContext()); watcher.addListener(listener); watcher.start(); - assertEquals("4.0", 2, getInstallableUnits(listener).length); + assertEquals("4.0", 4, getInstallableUnits(listener).length); assertEquals("4.1", 2, listener.getArtifactRepository().getArtifactKeys().length); try { @@ -112,7 +112,7 @@ public class RepositoryListenerTest extends AbstractProvisioningTest { } watcher.poll(); - assertEquals("5.0", 3, getInstallableUnits(listener).length); + assertEquals("5.0", 5, getInstallableUnits(listener).length); assertEquals("5.1", 3, listener.getArtifactRepository().getArtifactKeys().length); watcher.stop(); diff --git a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/provisional/p2/ui/dialogs/IUGeneralInfoPropertyPage.java b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/provisional/p2/ui/dialogs/IUGeneralInfoPropertyPage.java index c6f85a75d..a323de442 100644 --- a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/provisional/p2/ui/dialogs/IUGeneralInfoPropertyPage.java +++ b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/provisional/p2/ui/dialogs/IUGeneralInfoPropertyPage.java @@ -12,9 +12,11 @@ package org.eclipse.equinox.internal.provisional.p2.ui.dialogs; import java.net.MalformedURLException; import java.net.URL; +import java.util.Locale; import org.eclipse.equinox.internal.p2.ui.ProvUIMessages; import org.eclipse.equinox.internal.p2.ui.dialogs.IUPropertyPage; import org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit; +import org.eclipse.equinox.internal.provisional.p2.ui.query.IUPropertyUtils; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; @@ -52,10 +54,12 @@ public class IUGeneralInfoPropertyPage extends IUPropertyPage { layout.marginHeight = 0; composite.setLayout(layout); composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - addField(composite, ProvUIMessages.IUGeneralInfoPropertyPage_NameLabel, iu.getProperty(IInstallableUnit.PROP_NAME)); + //addField(composite, ProvUIMessages.IUGeneralInfoPropertyPage_NameLabel, iu.getProperty(IInstallableUnit.PROP_NAME)); + addField(composite, ProvUIMessages.IUGeneralInfoPropertyPage_NameLabel, IUPropertyUtils.getIUProperty(iu, IInstallableUnit.PROP_NAME, Locale.getDefault())); addField(composite, ProvUIMessages.IUGeneralInfoPropertyPage_IdentifierLabel, iu.getId()); addField(composite, ProvUIMessages.IUGeneralInfoPropertyPage_VersionLabel, iu.getVersion().toString()); - addField(composite, ProvUIMessages.IUGeneralInfoPropertyPage_ProviderLabel, iu.getProperty(IInstallableUnit.PROP_PROVIDER)); + //addField(composite, ProvUIMessages.IUGeneralInfoPropertyPage_ProviderLabel, iu.getProperty(IInstallableUnit.PROP_PROVIDER)); + addField(composite, ProvUIMessages.IUGeneralInfoPropertyPage_ProviderLabel, IUPropertyUtils.getIUProperty(iu, IInstallableUnit.PROP_PROVIDER, Locale.getDefault())); addField(composite, ProvUIMessages.IUGeneralInfoPropertyPage_ContactLabel, iu.getProperty(IInstallableUnit.PROP_CONTACT)); } diff --git a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/provisional/p2/ui/query/IUPropertyUtils.java b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/provisional/p2/ui/query/IUPropertyUtils.java new file mode 100644 index 000000000..3b9b87f17 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/provisional/p2/ui/query/IUPropertyUtils.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.provisional.p2.ui.query; + +import java.util.*; +import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper; +import org.eclipse.equinox.internal.p2.ui.ProvUIActivator; +import org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit; +import org.eclipse.equinox.internal.provisional.p2.metadata.query.InstallableUnitQuery; +import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepositoryManager; +import org.eclipse.equinox.internal.provisional.p2.query.Collector; + +public class IUPropertyUtils { + + public static String getIUProperty(IInstallableUnit iu, String propertyKey, Locale locale) { + String value = iu.getProperty(propertyKey); + if (value == null || value.length() <= 1 || value.charAt(0) != '%') + return value; + // else have a localizable property + String actualKey = value.substring(1); + String localizationBundles[] = buildLocalizationVariants(iu, locale); + + IMetadataRepositoryManager repoMgr = (IMetadataRepositoryManager) ServiceHelper.getService(ProvUIActivator.getContext(), IMetadataRepositoryManager.class.getName()); + + for (int i = 0; i < localizationBundles.length; i++) { + InstallableUnitQuery iuQuery = new InstallableUnitQuery(localizationBundles[i]); + Collector collected = repoMgr.query(iuQuery, new Collector(), null); + if (!collected.isEmpty()) { + for (Iterator iter = collected.iterator(); iter.hasNext();) { + IInstallableUnit localizationIU = (IInstallableUnit) iter.next(); + String translation = localizationIU.getProperty(actualKey); + if (translation != null) + return translation; + } + } + } + + return value; + } + + private static final String MANIFEST_NAME = "_manifest"; //$NON-NLS-1$ + private static final String PROPERTIES_NAME = "_properties"; //$NON-NLS-1$ + + /** + */ + private static String[] buildLocalizationVariants(IInstallableUnit iu, Locale locale) { + String id = iu.getId().toString(); + String nl = locale.toString(); + ArrayList result = new ArrayList(4); + int lastSeparator; + while (true) { + result.add(id + MANIFEST_NAME + '_' + nl + PROPERTIES_NAME); + lastSeparator = nl.lastIndexOf('_'); + if (lastSeparator == -1) + break; + nl = nl.substring(0, lastSeparator); + } + //add the empty suffix last (most general) + result.add(id + MANIFEST_NAME + PROPERTIES_NAME); + return (String[]) result.toArray(new String[result.size()]); + } + +} diff --git a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/metadata/UpdateSiteMetadataRepository.java b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/metadata/UpdateSiteMetadataRepository.java index eaee92037..21a44fe52 100644 --- a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/metadata/UpdateSiteMetadataRepository.java +++ b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/metadata/UpdateSiteMetadataRepository.java @@ -101,8 +101,10 @@ public class UpdateSiteMetadataRepository extends AbstractRepository implements mockManifest.put("Bundle-Version", entry.getVersion()); BundleDescription bundleDescription = bundleDesciptionFactory.getBundleDescription(mockManifest, null); IArtifactKey key = MetadataGeneratorHelper.createBundleArtifactKey(entry.getId(), entry.getVersion()); - IInstallableUnit bundleIU = MetadataGeneratorHelper.createEclipseIU(bundleDescription, null, entry.isUnpack(), key, extraProperties); - allSiteIUs.add(bundleIU); + IInstallableUnit[] bundleIUs = MetadataGeneratorHelper.createEclipseIU(bundleDescription, null, entry.isUnpack(), key, extraProperties); + for (int n = 0; n < bundleIUs.length; n++) { + allSiteIUs.add(bundleIUs[n]); + } } } |