diff options
Diffstat (limited to 'bundles/org.eclipse.e4.tools.services/src/org/eclipse/e4/tools/services/impl/MessageFactoryServiceImpl.java')
-rw-r--r-- | bundles/org.eclipse.e4.tools.services/src/org/eclipse/e4/tools/services/impl/MessageFactoryServiceImpl.java | 247 |
1 files changed, 0 insertions, 247 deletions
diff --git a/bundles/org.eclipse.e4.tools.services/src/org/eclipse/e4/tools/services/impl/MessageFactoryServiceImpl.java b/bundles/org.eclipse.e4.tools.services/src/org/eclipse/e4/tools/services/impl/MessageFactoryServiceImpl.java deleted file mode 100644 index 4273532f..00000000 --- a/bundles/org.eclipse.e4.tools.services/src/org/eclipse/e4/tools/services/impl/MessageFactoryServiceImpl.java +++ /dev/null @@ -1,247 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 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 - * Dirk Fauth <dirk.fauth@gmail.com> - modifications to instance creation - ******************************************************************************/ -package org.eclipse.e4.tools.services.impl; - -import java.lang.ref.Reference; -import java.lang.ref.SoftReference; -import java.lang.ref.WeakReference; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Locale; -import java.util.Map; -import java.util.Map.Entry; -import java.util.MissingResourceException; -import java.util.ResourceBundle; - -import javax.annotation.PostConstruct; - -import org.eclipse.e4.tools.services.IMessageFactoryService; -import org.eclipse.e4.tools.services.Message; -import org.eclipse.e4.tools.services.Message.ReferenceType; -import org.eclipse.e4.tools.services.ToolsServicesActivator; -import org.eclipse.osgi.service.localization.BundleLocalization; -import org.osgi.framework.Bundle; -import org.osgi.framework.FrameworkUtil; -import org.osgi.service.log.LogService; - -public class MessageFactoryServiceImpl implements IMessageFactoryService { - - private static LogService logService = ToolsServicesActivator.getDefault().getLogService(); - - // Cache so when multiple instance use the same message class - private Map<Object, Reference<Object>> SOFT_CACHE = Collections - .synchronizedMap(new HashMap<Object, Reference<Object>>()); - - private Map<Object, Reference<Object>> WEAK_CACHE = Collections - .synchronizedMap(new HashMap<Object, Reference<Object>>()); - - private int CLEANUPCOUNT = 0; - - @Override - public <M> M getMessageInstance(final Locale locale, final Class<M> messages, final BundleLocalization localization) { - String key = messages.getName() + "_" + locale; //$NON-NLS-1$ - - final Message annotation = messages.getAnnotation(Message.class); - Map<Object, Reference<Object>> cache = null; - ReferenceType type = ReferenceType.NONE; - - if (++CLEANUPCOUNT > 1000) { - Iterator<Entry<Object, Reference<Object>>> it = WEAK_CACHE - .entrySet().iterator(); - while (it.hasNext()) { - if (it.next().getValue().get() == null) { - it.remove(); - } - } - - it = SOFT_CACHE.entrySet().iterator(); - while (it.hasNext()) { - if (it.next().getValue().get() == null) { - it.remove(); - } - } - CLEANUPCOUNT = 0; - } - - if (annotation == null - || annotation.referenceType() == ReferenceType.SOFT) { - cache = SOFT_CACHE; - type = ReferenceType.SOFT; - } else if (annotation.referenceType() == ReferenceType.WEAK) { - cache = WEAK_CACHE; - type = ReferenceType.WEAK; - } - - if (cache != null && cache.containsKey(key)) { - @SuppressWarnings("unchecked") - Reference<M> ref = (Reference<M>) cache.get(key); - M o = ref.get(); - if (o != null) { - return o; - } - cache.remove(key); - } - - M instance; - - if (System.getSecurityManager() == null) { - instance = createInstance(locale, messages, annotation, localization); - } else { - instance = AccessController.doPrivileged(new PrivilegedAction<M>() { - - public M run() { - return createInstance(locale, messages, annotation, localization); - } - - }); - } - - if (cache != null) { - if (type == ReferenceType.SOFT) { - cache.put(key, new SoftReference<Object>(instance)); - } else if (type == ReferenceType.WEAK) { - cache.put(key, new WeakReference<Object>(instance)); - } - } - - return instance; - } - - /** - * Creates and returns an instance of the of a given messages class for the given {@link Locale}. - * The message class gets instantiated and the fields are initialized with values out of a {@link ResourceBundle}. - * As there are several options to specify the location of the {@link ResourceBundle} to load, the - * following search order is used: - * <ol> - * <li>URI location<br/> - * If the message class is annotated with <code>@Message</code> and the <i>contributorURI</i> - * attribute is set, the {@link ResourceBundle} is searched at the specified location</li> - * <li>Relative location<br/> - * If the message class is not annotated with <code>@Message</code> and a contributorURI - * attribute value or there is no {@link ResourceBundle} found at the specified location, a - * {@link ResourceBundle} with the same name in the same package as the message class is searched.</li> - * <li>Bundle localization<br/> - * If there is no {@link ResourceBundle} found by URI or relative location, the OSGi {@link ResourceBundle} - * configured in the MANIFEST.MF is tried to load.</li> - * </ol> - * Note: Even if there is no {@link ResourceBundle} found in any of the mentioned locations, this method will - * not break. In this case the fields of the message class will get initialized with values that look - * like <code>!key!</code> to indicate that there is no translation value found for that key. - * - * @param locale The {@link Locale} for which the message class instance is requested. - * @param messages The type of the message class whose instance is requested. - * @param annotation The annotation that is used in the message class. If specified it is needed - * to retrieve the URI of the location to search for the {@link ResourceBundle}. - * @param localization The service that is needed to retrieve {@link ResourceBundle} objects from a bundle - * with a given locale. - * - * @return The created instance of the given messages class and {@link Locale} or <code>null</code> - * if an error occured on creating the instance. - */ - private static <M> M createInstance(Locale locale, Class<M> messages, - Message annotation, BundleLocalization localization) { - - ResourceBundle resourceBundle = null; - if (annotation != null && annotation.contributorURI().length() > 0) { - resourceBundle = ResourceBundleHelper.getResourceBundleForUri(annotation.contributorURI(), locale, localization); - } - - if (resourceBundle == null) { - //check for the resource bundle relative to the messages class - String baseName = messages.getName().replace('.', '/'); - - try { - resourceBundle = ResourceBundleHelper.getEquinoxResourceBundle(baseName, locale, messages.getClassLoader()); - } - catch (MissingResourceException e) { - //do nothing as this just means there is no resource bundle named - //like the messages class in the same package - //therefore we will go on and search for the OSGi resource bundle - } - } - - if (resourceBundle == null) { - //retrieve the OSGi resource bundle - Bundle bundle = FrameworkUtil.getBundle(messages); - resourceBundle = localization.getLocalization(bundle, locale.toString()); - } - - //always create a provider, if there is no resource bundle found, simply the modified keys will - //be returned by this provider to show that there is something wrong on loading it - ResourceBundleTranslationProvider provider = new ResourceBundleTranslationProvider(resourceBundle); - - M instance = null; - try { - instance = messages.newInstance(); - Field[] fields = messages.getDeclaredFields(); - - for (int i = 0; i < fields.length; i++) { - if (!fields[i].isAccessible()) { - fields[i].setAccessible(true); - } - - fields[i].set(instance, - provider.translate(fields[i].getName())); - } - } catch (InstantiationException e) { - if (logService != null) - logService.log(LogService.LOG_ERROR, - "Instantiation of messages class failed", e); //$NON-NLS-1$ - } catch (IllegalAccessException e) { - if (logService != null) - logService.log(LogService.LOG_ERROR, - "Failed to access messages class", e); //$NON-NLS-1$ - } - - //invoke the method annotated with @PostConstruct - processPostConstruct(instance, messages); - - return instance; - } - - /** - * Searches for the method annotated {@link PostConstruct} in the messages class. - * If there is one found it will be executed. - * <p> - * Note: The method annotated with {@link PostConstruct} does not support method injection - * because we are not using the injection mechanism to call. - * @param messageObject The message instance of the given class where the method annotated with - * {@link PostConstruct} should be called - * @param messageClass The type of the message class whose instance is requested. - */ - private static void processPostConstruct(Object messageObject, Class<?> messageClass) { - if (messageObject != null) { - Method[] methods = messageClass.getDeclaredMethods(); - for (int i = 0; i < methods.length; i++) { - Method method = methods[i]; - if (!method.isAnnotationPresent(PostConstruct.class)) { - continue; - } - else { - try { - method.invoke(messageObject); - } catch (Exception e) { - if (logService != null) - logService.log(LogService.LOG_ERROR, - "Exception on trying to execute the @PostConstruct annotated method in " + messageClass, e); //$NON-NLS-1$ - } - } - } - } - } - -}
\ No newline at end of file |