1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.primefaces.extensions.component.localized;
23
24 import java.io.IOException;
25 import java.net.URISyntaxException;
26 import java.net.URL;
27 import java.nio.file.Files;
28 import java.nio.file.Path;
29 import java.nio.file.Paths;
30 import java.util.Locale;
31
32 import javax.el.ExpressionFactory;
33 import javax.faces.FacesException;
34 import javax.faces.component.UIComponent;
35 import javax.faces.context.FacesContext;
36 import javax.servlet.ServletContext;
37
38 import org.primefaces.extensions.config.PrimeExtensionsEnvironment;
39 import org.primefaces.extensions.util.CommonMarkWrapper;
40 import org.primefaces.renderkit.CoreRenderer;
41 import org.primefaces.util.EscapeUtils;
42 import org.primefaces.util.FacetUtils;
43 import org.primefaces.util.LangUtils;
44
45
46
47
48
49
50
51 public class LocalizedRenderer extends CoreRenderer {
52
53 public static final String WEB_FOLDER = "WEB-INF/pfe-localized";
54 public static final String QUARKUS_FOLDER = "pfe-localized";
55
56 @Override
57 public void encodeEnd(final FacesContext context, final UIComponent component) throws IOException {
58 final Localized localized = (Localized) component;
59 encodeMarkup(context, localized);
60 }
61
62 protected void encodeMarkup(final FacesContext context, final Localized localized) throws IOException {
63 if (LangUtils.isBlank(localized.getName())) {
64 encodeFromFacet(context, localized);
65 }
66 else {
67 encodeFromFile(context, localized);
68 }
69 }
70
71 protected void encodeFromFacet(final FacesContext context, final Localized localized) throws IOException {
72 final Locale locale = localized.calculateLocale(context);
73 final String language = locale.getLanguage();
74 final String country = locale.getCountry();
75 resolveFacet(localized, language, country).encodeAll(context);
76 }
77
78 protected UIComponent resolveFacet(final Localized localized, final String language, final String country) {
79 UIComponent facet = localized.getFacet(language + "_" + country);
80 if (FacetUtils.shouldRenderFacet(facet)) {
81 return facet;
82 }
83 facet = localized.getFacet(language);
84 if (FacetUtils.shouldRenderFacet(facet)) {
85 return facet;
86 }
87 facet = localized.getFacet("default");
88 if (FacetUtils.shouldRenderFacet(facet)) {
89 return facet;
90 }
91 throw new FacesException("No facet found for " + language + "_" + country + ", nor a 'default' facet");
92 }
93
94 protected void encodeFromFile(final FacesContext context, final Localized localized) throws IOException {
95 final Path filePath = resolvePath(context, localized);
96 final byte[] bytes = Files.readAllBytes(filePath);
97 String value = new String(bytes);
98 if (localized.isEvalEl()) {
99 value = evaluateEl(context, value);
100 }
101 if (localized.isEscape()) {
102 value = EscapeUtils.forHtml(value);
103 }
104 if (localized.isMarkdown()) {
105 value = toHTML(context, value);
106 }
107 context.getResponseWriter().append(value);
108 }
109
110 protected Path resolvePath(final FacesContext context, final Localized localized) {
111 final ServletContext servletContext = ((ServletContext) context.getExternalContext().getContext());
112 final String web = servletContext.getRealPath(WEB_FOLDER);
113 final String meta = servletContext.getRealPath(QUARKUS_FOLDER);
114 final Locale locale = localized.calculateLocale(context);
115 final String language = locale.getLanguage();
116 final String country = locale.getCountry();
117 final String folder = localized.getFolder();
118 final String name = localized.getName();
119 Path path = resolvePath(web, folder, name, language, country);
120 if (path == null) {
121 path = resolvePath(web, null, name, language, country);
122 }
123 if (path == null) {
124 path = resolvePath(meta, folder, name, language, country);
125 }
126 if (path == null) {
127 path = resolvePath(meta, null, name, language, country);
128 }
129 if (path == null) {
130 throw new IllegalStateException("Cannot find Localized file for: " + localized.getClientId(context));
131 }
132 return path;
133 }
134
135 protected Path resolvePath(final String base, final String folder, final String name, final String language,
136 final String country) {
137 final String baseFolder = LangUtils.isBlank(folder)
138 ? base
139 : base + "/" + folder;
140 Path path = existingPath(baseFolder, name + "_" + language + "_" + country);
141 if (path == null) {
142 path = existingPath(baseFolder, name + "_" + language);
143 }
144 if (path == null) {
145 path = existingPath(baseFolder, name);
146 }
147 return path;
148 }
149
150 protected Path existingPath(final String first, final String more) {
151 final Path path = Paths.get(first, more);
152 Path existingPath = path.toFile().exists() ? path : null;
153 if (existingPath == null) {
154 final String resourcePath = first + "/" + more;
155 try {
156
157 final URL url = Thread.currentThread().getContextClassLoader().getResource(resourcePath);
158 if (url != null) {
159 existingPath = Paths.get(url.toURI());
160 }
161 }
162 catch (final URISyntaxException e) {
163 throw new RuntimeException(e);
164 }
165 }
166 return existingPath;
167 }
168
169 protected String toHTML(final FacesContext context, final String value) {
170 if (!PrimeExtensionsEnvironment.getCurrentInstance(context).isCommonmarkAvailable()) {
171 throw new FacesException("CommonMark not available.");
172 }
173 return CommonMarkWrapper.toHTML(value);
174 }
175
176 protected String evaluateEl(final FacesContext context, final String value) {
177 return (String) ExpressionFactory.newInstance()
178 .createValueExpression(context.getELContext(), value, String.class)
179 .getValue(context.getELContext());
180 }
181 }