Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 55526f51e14b3ad7ca2fe4e456fdaf4b2104d41e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/*******************************************************************************
 * Copyright (c) 2015 Obeo.
 * 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:
 *    Obeo - initial API and implementation
 *******************************************************************************/
package org.eclipse.eef.properties.ui.legacy.internal;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.PrivilegedAction;

import org.eclipse.emf.common.EMFPlugin;

/**
 * Helper class with bundle-independent code, that can be reused by other I18N classes local to each plug-in.
 *
 * @author pcdavid
 */
public final class I18N {
	/**
	 * Used to mark a {@code public static String} field of a class as an externalized string, whose actual value will
	 * depend on the locale used at runtime. The optional value corresponds to the key in the {@code ResourceLocator};
	 * if absent, the name of the field itself is used as key.
	 *
	 * @author pcdavid
	 */
	@Retention(RetentionPolicy.RUNTIME)
	@Target(ElementType.FIELD)
	public @interface TranslatableMessage {
		/**
		 * The (optional) value of the message key. If absent, the key is assumed to be the same as the Java field's
		 * name.
		 * 
		 * @return the message key, if different from the field name.
		 */
		String[] value() default {};
	}

	/**
	 * The constructor.
	 */
	private I18N() {
		// Prevent instantiation
	}

	/**
	 * Initializes the value of a class's {@code TranslatableMessage}s using the specified plugin as
	 * {@code ResourceLocator}.
	 *
	 * @param messagesClass
	 *            the class which defines the fields to initialize.
	 * @param plugin
	 *            the plugin from which to obtain the localized value of the fields.
	 */
	public static void initializeMessages(final Class<?> messagesClass, final EMFPlugin plugin) {
		if (System.getSecurityManager() == null) {
			load(plugin, messagesClass);
			return;
		}
		AccessController.doPrivileged(new PrivilegedAction<Void>() {
			@Override
			public Void run() {
				load(plugin, messagesClass);
				return null;
			}
		});
	}

	/**
	 * Loads the message class with the given {@link EMFPlugin}.
	 *
	 * @param plugin
	 *            The plugin
	 * @param messagesClass
	 *            The message class
	 */
	private static void load(EMFPlugin plugin, Class<?> messagesClass) {
		for (Field field : messagesClass.getDeclaredFields()) {
			if (isMessageField(field)) {
				initialize(field, plugin);
			}
		}
	}

	/**
	 * Indicates if the given field is a message field.
	 *
	 * @param field
	 *            The field
	 * @return <code>true</code> if the given field is a message field, <code>false</code> otherwise.
	 */
	private static boolean isMessageField(Field field) {
		int mods = field.getModifiers();
		boolean modsOK = Modifier.isPublic(mods) && Modifier.isStatic(mods) && !Modifier.isFinal(mods);
		return modsOK && field.isAnnotationPresent(I18N.TranslatableMessage.class) && field.getType() == String.class;
	}

	/**
	 * Initializes the given field used the plugin.
	 *
	 * @param field
	 *            The field to initialize
	 * @param plugin
	 *            The plugin
	 */
	private static void initialize(Field field, EMFPlugin plugin) {
		String key = getKey(field);
		String value = plugin.getString(key);
		if (!field.isAccessible()) {
			field.setAccessible(true);
		}
		try {
			field.set(null, value);
		} catch (IllegalArgumentException e) {
			plugin.log(e);
		} catch (IllegalAccessException e) {
			plugin.log(e);
		}
	}

	/**
	 * Returns the key for the given field.
	 *
	 * @param field
	 *            The field
	 * @return The key of the field
	 */
	private static String getKey(Field field) {
		I18N.TranslatableMessage annot = field.getAnnotation(I18N.TranslatableMessage.class);
		String[] key = annot.value();
		if (key == null || key.length == 0) {
			key = new String[] { field.getName() };
		}
		return key[0];
	}
}

Back to the top