Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDirk Fauth2013-05-17 13:31:00 +0000
committerTom Schindl2013-05-17 13:31:00 +0000
commitd2037ceadfa7b70e30d1540146a1c0a082f8de48 (patch)
tree576cce99f675498ed3a31f85693ded0daae52b99
parent8973e881a16149b97efea12df3b00c32ff622d54 (diff)
downloadorg.eclipse.e4.tools-d2037ceadfa7b70e30d1540146a1c0a082f8de48.tar.gz
org.eclipse.e4.tools-d2037ceadfa7b70e30d1540146a1c0a082f8de48.tar.xz
org.eclipse.e4.tools-d2037ceadfa7b70e30d1540146a1c0a082f8de48.zip
Bug 405936 - Update ProjectOSGiTranslationProvider to use the new
message extensions
-rw-r--r--bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/common/component/AbstractComponentEditor.java17
-rw-r--r--bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/ModelEditor.java7
-rw-r--r--bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/ControlFactory.java12
-rw-r--r--bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/properties/ProjectOSGiTranslationProvider.java287
4 files changed, 233 insertions, 90 deletions
diff --git a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/common/component/AbstractComponentEditor.java b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/common/component/AbstractComponentEditor.java
index 191b2ad6..830dde39 100644
--- a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/common/component/AbstractComponentEditor.java
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/common/component/AbstractComponentEditor.java
@@ -13,7 +13,6 @@ package org.eclipse.e4.tools.emf.ui.common.component;
import java.util.Collections;
import java.util.List;
import javax.inject.Inject;
-import javax.inject.Named;
import org.eclipse.core.databinding.observable.list.IObservableList;
import org.eclipse.core.databinding.observable.value.WritableValue;
import org.eclipse.e4.core.di.annotations.Optional;
@@ -26,7 +25,7 @@ import org.eclipse.e4.tools.emf.ui.internal.common.properties.ProjectOSGiTransla
import org.eclipse.e4.tools.services.IClipboardService.Handler;
import org.eclipse.e4.tools.services.IResourcePool;
import org.eclipse.e4.tools.services.Translation;
-import org.eclipse.e4.tools.services.impl.AbstractTranslationProvider;
+import org.eclipse.e4.tools.services.impl.ResourceBundleTranslationProvider;
import org.eclipse.e4.ui.model.application.MApplicationElement;
import org.eclipse.e4.ui.model.application.ui.MUILabel;
import org.eclipse.emf.databinding.FeaturePath;
@@ -74,10 +73,6 @@ public abstract class AbstractComponentEditor {
@Optional
private ProjectOSGiTranslationProvider translationProvider;
- @Inject
- @Named(TranslationService.LOCALE)
- private String locale;
-
private Composite editorControl;
public EditingDomain getEditingDomain() {
@@ -134,9 +129,9 @@ public abstract class AbstractComponentEditor {
}
/**
- * Translates an input <code>string</code> using the current
- * {@link AbstractTranslationProvider} and <code>locale</code> from the
- * {@link TranslationService}.
+ * Translates an input <code>String</code> using the current
+ * {@link ResourceBundleTranslationProvider} and <code>locale</code> from
+ * the {@link TranslationService}.
*
* @param string
* the string to translate, may not be null.
@@ -144,7 +139,7 @@ public abstract class AbstractComponentEditor {
* translated.
*/
public String translate(String string) {
- return ControlFactory.tr(translationProvider, locale, string);
+ return ControlFactory.tr(translationProvider, string);
}
/**
@@ -157,7 +152,7 @@ public abstract class AbstractComponentEditor {
}
protected String getLocalizedLabel(MUILabel element) {
- return ControlFactory.getLocalizedLabel(translationProvider, element, locale);
+ return ControlFactory.getLocalizedLabel(translationProvider, element);
}
private boolean isFocusChild(Control control) {
diff --git a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/ModelEditor.java b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/ModelEditor.java
index cd285a87..35b417a1 100644
--- a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/ModelEditor.java
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/ModelEditor.java
@@ -45,6 +45,7 @@ import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.e4.core.di.annotations.Optional;
import org.eclipse.e4.core.di.extensions.Preference;
import org.eclipse.e4.core.services.contributions.IContributionFactory;
+import org.eclipse.e4.core.services.translation.TranslationService;
import org.eclipse.e4.tools.emf.ui.common.EStackLayout;
import org.eclipse.e4.tools.emf.ui.common.IContributionClassCreator;
import org.eclipse.e4.tools.emf.ui.common.IEditorDescriptor;
@@ -328,10 +329,10 @@ public class ModelEditor {
this.context.set(ModelEditor.class, this);
this.obsManager = new ObservablesManager();
if (project != null) {
- ProjectOSGiTranslationProvider translationProvider = new ProjectOSGiTranslationProvider(project) {
+ ProjectOSGiTranslationProvider translationProvider = new ProjectOSGiTranslationProvider(project, (String) this.context.get(TranslationService.LOCALE)) {
@Override
- protected void clearCache() {
- super.clearCache();
+ protected void updateResourceBundle() {
+ super.updateResourceBundle();
viewer.getControl().getDisplay().asyncExec(new Runnable() {
public void run() {
diff --git a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/ControlFactory.java b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/ControlFactory.java
index 905fa66c..fd76e8b3 100644
--- a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/ControlFactory.java
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/ControlFactory.java
@@ -814,11 +814,11 @@ public class ControlFactory {
}
- public static String getLocalizedLabel(ProjectOSGiTranslationProvider translationProvider, MUILabel element, String locale) {
- return getLocalizedValue(translationProvider, (MApplicationElement) element, UiPackageImpl.Literals.UI_LABEL__LABEL, UiPackageImpl.Literals.UI_LABEL___GET_LOCALIZED_LABEL, locale);
+ public static String getLocalizedLabel(ProjectOSGiTranslationProvider translationProvider, MUILabel element) {
+ return getLocalizedValue(translationProvider, (MApplicationElement) element, UiPackageImpl.Literals.UI_LABEL__LABEL, UiPackageImpl.Literals.UI_LABEL___GET_LOCALIZED_LABEL);
}
- public static String getLocalizedValue(ProjectOSGiTranslationProvider translationProvider, MApplicationElement element, EStructuralFeature feature, EOperation operation, String locale) {
+ public static String getLocalizedValue(ProjectOSGiTranslationProvider translationProvider, MApplicationElement element, EStructuralFeature feature, EOperation operation) {
EObject eo = (EObject) element;
if (translationProvider == null) {
try {
@@ -834,16 +834,16 @@ public class ControlFactory {
String value = (String) eo.eGet(feature);
if (value != null && value.trim().length() > 0) {
- return tr(translationProvider, locale, value);
+ return tr(translationProvider, value);
}
return null;
}
- public static String tr(ProjectOSGiTranslationProvider translationProvider, String locale, String label) {
+ public static String tr(ProjectOSGiTranslationProvider translationProvider, String label) {
if (label.startsWith("%") && translationProvider != null) { //$NON-NLS-1$
String key = label.substring(1);
- String translation = translationProvider.translate(locale, key);
+ String translation = translationProvider.translate(key);
return translation == key ? label : translation;
}
return label;
diff --git a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/properties/ProjectOSGiTranslationProvider.java b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/properties/ProjectOSGiTranslationProvider.java
index 436711cd..016d28ba 100644
--- a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/properties/ProjectOSGiTranslationProvider.java
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/properties/ProjectOSGiTranslationProvider.java
@@ -1,21 +1,19 @@
-/*******************************************************************************
- * Copyright (c) 2010 BestSolution.at 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:
- * Tom Schindl <tom.schindl@bestsolution.at> - initial API and implementation
- ******************************************************************************/
package org.eclipse.e4.tools.emf.ui.internal.common.properties;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
-import java.util.ArrayList;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
import java.util.List;
+import java.util.Locale;
+import java.util.PropertyResourceBundle;
+import java.util.ResourceBundle;
+import java.util.ResourceBundle.Control;
+import javax.inject.Inject;
+import javax.inject.Named;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResourceChangeEvent;
@@ -24,18 +22,46 @@ import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.runtime.CoreException;
-import org.eclipse.e4.tools.services.impl.AbstractTranslationProvider;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.core.services.translation.TranslationService;
+import org.eclipse.e4.tools.services.impl.ResourceBundleHelper;
+import org.eclipse.e4.tools.services.impl.ResourceBundleTranslationProvider;
+import org.osgi.framework.Constants;
-public abstract class ProjectOSGiTranslationProvider extends AbstractTranslationProvider {
+public class ProjectOSGiTranslationProvider extends ResourceBundleTranslationProvider {
+
+ public static final String META_INF_DIRECTORY_NAME = "META-INF"; //$NON-NLS-1$
+ public static final String MANIFEST_DEFAULT_PATH = "META-INF/MANIFEST.MF"; //$NON-NLS-1$
+
+ /**
+ * The {@link IProject} this translation provider is connected to
+ */
private IProject project;
- private List<String> observedFiles = new ArrayList<String>();
- private IResourceChangeListener listener;
+ /**
+ * The manifest header identifying the base name of the bundle's
+ * localization entries.
+ */
private String basename;
+ /**
+ * The Locale to use for translations.
+ */
+ private Locale locale;
+
+ /**
+ * @param project
+ * The {@link IProject} this translation provider should be
+ * connected to.
+ * @param locale
+ * The initial {@link Locale} for which this translation provider
+ * should be created.
+ */
+ public ProjectOSGiTranslationProvider(IProject project, String locale) {
+ // create the translation provider with no initial ResourceBundle as we
+ // need to calculate it first
+ super(null);
- public ProjectOSGiTranslationProvider(IProject project) {
- super();
this.project = project;
- this.listener = new IResourceChangeListener() {
+ this.project.getWorkspace().addResourceChangeListener(new IResourceChangeListener() {
public void resourceChanged(IResourceChangeEvent event) {
if (event.getType() == IResourceChangeEvent.POST_CHANGE) {
@@ -52,59 +78,92 @@ public abstract class ProjectOSGiTranslationProvider extends AbstractTranslation
}
}
}
- };
- this.project.getWorkspace().addResourceChangeListener(listener);
- IFile f = this.project.getFile("META-INF/MANIFEST.MF"); //$NON-NLS-1$
+ });
+ setLocale(locale, false);
+
+ IFile f = this.project.getFile(MANIFEST_DEFAULT_PATH);
if (f.exists()) {
handleManifestChange(f);
} else {
- basename = "OSGI-INF/l10n/bundle"; //$NON-NLS-1$
+ basename = Constants.BUNDLE_LOCALIZATION_DEFAULT_BASENAME;
}
}
- boolean visit(IResourceDelta delta) throws CoreException {
+ @Inject
+ void setLocale(@Named(TranslationService.LOCALE) String locale, @Optional Boolean performUpdate) {
+ try {
+ this.locale = locale == null ? Locale.getDefault() : ResourceBundleHelper.toLocale(locale);
+ } catch (Exception e) {
+ this.locale = Locale.getDefault();
+ }
+
+ if (performUpdate == null || performUpdate)
+ updateResourceBundle();
+ }
+
+ /**
+ *
+ * @param delta
+ * The resource delta that represents the changes in the state of
+ * a resource tree between two discrete points in time.
+ * @return <code>true</code> if the resource delta's children should be
+ * visited; <code>false</code> if they should be skipped.
+ */
+ boolean visit(IResourceDelta delta) {
if (delta.getResource() instanceof IWorkspaceRoot) {
return true;
- } else if (delta.getResource().equals(project)) {
+ } else if (delta.getResource().equals(this.project)) {
return true;
- } else if (delta.getResource().getProjectRelativePath().toString().equals("META-INF")) { //$NON-NLS-1$
+ } else if (delta.getResource().getProjectRelativePath().toString().equals(META_INF_DIRECTORY_NAME)) {
return true;
- } else if (delta.getResource().getProjectRelativePath().toString().equals("META-INF/MANIFEST.MF")) { //$NON-NLS-1$
+ } else if (delta.getResource().getProjectRelativePath().toString().equals(MANIFEST_DEFAULT_PATH)) {
handleManifestChange((IFile) delta.getResource());
return false;
- }
-
- for (String o : observedFiles) {
- if (delta.getResource().getProjectRelativePath().toString().equals(o)) {
- clearCache();
+ } else if (delta.getResource() instanceof IFile) {
+ String filename = ((IFile) delta.getResource()).getName();
+ // extract base bundle name out of local basename
+ String fileBaseName = this.basename.substring(this.basename.lastIndexOf("/") + 1, this.basename.length()); //$NON-NLS-1$
+ if (filename.startsWith(fileBaseName)) {
+ updateResourceBundle();
return false;
}
+ }
- String[] p = o.split("/"); //$NON-NLS-1$
- int i = 0;
- String path = ""; //$NON-NLS-1$
- do {
- path += p[i];
- if (delta.getResource().getProjectRelativePath().toString().equals(path)) {
- return true;
- }
- path += "/"; //$NON-NLS-1$
- } while (++i < p.length);
+ if (delta.getResource().getProjectRelativePath().toString().equals(this.basename)) {
+ updateResourceBundle();
+ return false;
}
+ String[] p = this.basename.split("/"); //$NON-NLS-1$
+ int i = 0;
+ String path = ""; //$NON-NLS-1$
+ do {
+ path += p[i];
+ if (delta.getResource().getProjectRelativePath().toString().equals(path)) {
+ return true;
+ }
+ path += "/"; //$NON-NLS-1$
+ } while (++i < p.length);
+
return false;
}
+ /**
+ * Will check if the manifest header identifying the base name of the
+ * bundle's localization entries has changed and if so it will update the
+ * underlying {@link ResourceBundle} and clear the caches.
+ *
+ * @param file
+ * The reference to the manifest file of the current project.
+ */
private void handleManifestChange(IFile file) {
try {
String newValue = extractBasenameFromManifest(file);
if (!newValue.equals(basename)) {
+ basename = newValue;
if (basename != null) {
- basename = newValue;
- clearCache();
- } else {
- basename = newValue;
+ updateResourceBundle();
}
}
@@ -117,14 +176,29 @@ public abstract class ProjectOSGiTranslationProvider extends AbstractTranslation
}
}
+ /**
+ * Extracts the manifest header identifying the base name of the bundle's
+ * localization entries.
+ *
+ * @param file
+ * The reference to the manifest file of the current project.
+ * @return The manifest header identifying the base name of the bundle's
+ * localization entries.
+ * @throws CoreException
+ * If loading the contents of the given {@link IFile} fails
+ * @throws IOException
+ * If reading out of the given file fails.
+ *
+ * @see IFile#getContents()
+ */
public static String extractBasenameFromManifest(IFile file) throws CoreException, IOException {
InputStream in = file.getContents();
BufferedReader r = new BufferedReader(new InputStreamReader(in));
String line;
- String newValue = "OSGI-INF/l10n/bundle"; //$NON-NLS-1$
+ String newValue = Constants.BUNDLE_LOCALIZATION_DEFAULT_BASENAME;
while ((line = r.readLine()) != null) {
- if (line.startsWith("Bundle-Localization:")) { //$NON-NLS-1$
- newValue = line.substring("Bundle-Localization:".length()).trim(); //$NON-NLS-1$
+ if (line.startsWith(Constants.BUNDLE_LOCALIZATION)) {
+ newValue = line.substring(Constants.BUNDLE_LOCALIZATION.length() + 1).trim();
break;
}
}
@@ -133,33 +207,106 @@ public abstract class ProjectOSGiTranslationProvider extends AbstractTranslation
return newValue;
}
- @Override
- protected InputStream getResourceAsStream(String name) {
- IFile f = project.getFile(name);
- observedFiles.add(name);
- try {
- if (f.exists()) {
- return f.getContents();
+ /**
+ * Reloads the underlying ResourceBundle.
+ */
+ protected void updateResourceBundle() {
+ setResourceBundle(ResourceBundleHelper.getEquinoxResourceBundle(this.basename, this.locale, new ProjectResourceBundleControl(true), new ProjectResourceBundleControl(false)));
+ }
+
+ /**
+ * Specialization of {@link Control} which loads the {@link ResourceBundle}
+ * by using file structures of a project instead of using a classloader.
+ *
+ * @author Dirk Fauth
+ */
+ class ProjectResourceBundleControl extends ResourceBundle.Control {
+
+ /**
+ * Flag to determine whether the default locale should be used as
+ * fallback locale in case there is no {@link ResourceBundle} found for
+ * the specified locale.
+ */
+ private final boolean useFallback;
+
+ /**
+ * @param useFallback
+ * <code>true</code> if the default locale should be used as
+ * fallback locale in the search path or <code>false</code>
+ * if there should be no fallback.
+ */
+ ProjectResourceBundleControl(boolean useFallback) {
+ this.useFallback = useFallback;
+ }
+
+ @Override
+ public ResourceBundle newBundle(String baseName, Locale locale, String format, ClassLoader loader, boolean reload) throws IllegalAccessException, InstantiationException, IOException {
+
+ String bundleName = toBundleName(baseName, locale);
+ ResourceBundle bundle = null;
+ if (format.equals("java.properties")) { //$NON-NLS-1$
+ final String resourceName = toResourceName(bundleName, "properties"); //$NON-NLS-1$
+ InputStream stream = null;
+ try {
+ stream = AccessController.doPrivileged(new PrivilegedExceptionAction<InputStream>() {
+ public InputStream run() throws IOException {
+ return getResourceAsStream(resourceName);
+ }
+ });
+ } catch (PrivilegedActionException e) {
+ throw (IOException) e.getException();
+ }
+ if (stream != null) {
+ try {
+ bundle = new PropertyResourceBundle(stream);
+ } finally {
+ stream.close();
+ }
+ }
} else {
- return null;
+ throw new IllegalArgumentException("unknown format: " + format); //$NON-NLS-1$
}
- } catch (CoreException e) {
- return null;
+ return bundle;
}
- }
- @Override
- protected void clearCache() {
- super.clearCache();
- observedFiles.clear();
- }
+ /**
+ * Loads the properties file by using the {@link IProject} of the
+ * {@link ProjectOSGiTranslationProvider}.
+ *
+ * @param name
+ * @return The {@link InputStream} to the properties file to load
+ */
+ protected InputStream getResourceAsStream(String name) {
+ IFile f = project.getFile(name);
+ try {
+ if (f.exists()) {
+ return f.getContents();
+ } else {
+ return null;
+ }
+ } catch (CoreException e) {
+ return null;
+ }
+ }
- @Override
- protected String getBasename() {
- return basename;
- }
+ @Override
+ public List<String> getFormats(String baseName) {
+ return FORMAT_PROPERTIES;
+ }
- public void dispose() {
+ @Override
+ public Locale getFallbackLocale(String baseName, Locale locale) {
+ return this.useFallback ? super.getFallbackLocale(baseName, locale) : null;
+ }
+ // this implementation simply doesn't cache the values in the
+ // ResourceBundle. If we recognize performance issues in the
+ // Application Model Editor because of this we should consider
+ // returning 0 here and overriding needsReload() with the information
+ // which bundle needs to be reloaded
+ @Override
+ public long getTimeToLive(String baseName, Locale locale) {
+ return TTL_DONT_CACHE;
+ }
}
-} \ No newline at end of file
+}

Back to the top