001
014
015 package com.liferay.portal.model;
016
017 import com.liferay.portal.kernel.log.Log;
018 import com.liferay.portal.kernel.log.LogFactoryUtil;
019 import com.liferay.portal.kernel.security.pacl.DoPrivileged;
020 import com.liferay.portal.kernel.util.GetterUtil;
021 import com.liferay.portal.kernel.util.ListUtil;
022 import com.liferay.portal.kernel.util.PropsKeys;
023 import com.liferay.portal.kernel.util.StringPool;
024 import com.liferay.portal.kernel.util.StringUtil;
025 import com.liferay.portal.kernel.util.Tuple;
026 import com.liferay.portal.kernel.util.Validator;
027 import com.liferay.portal.kernel.xml.Document;
028 import com.liferay.portal.kernel.xml.Element;
029 import com.liferay.portal.kernel.xml.SAXReader;
030 import com.liferay.portal.service.ClassNameLocalServiceUtil;
031 import com.liferay.portal.util.PropsUtil;
032 import com.liferay.util.PwdGenerator;
033
034 import java.io.InputStream;
035
036 import java.net.URL;
037
038 import java.util.ArrayList;
039 import java.util.Collections;
040 import java.util.Enumeration;
041 import java.util.HashMap;
042 import java.util.LinkedHashMap;
043 import java.util.List;
044 import java.util.Map;
045 import java.util.Set;
046 import java.util.TreeMap;
047 import java.util.TreeSet;
048
049
053 @DoPrivileged
054 public class ModelHintsImpl implements ModelHints {
055
056 public void afterPropertiesSet() {
057 _hintCollections = new HashMap<String, Map<String, String>>();
058 _defaultHints = new HashMap<String, Map<String, String>>();
059 _modelFields = new HashMap<String, Object>();
060 _models = new TreeSet<String>();
061
062 try {
063 ClassLoader classLoader = getClass().getClassLoader();
064
065 String[] configs = StringUtil.split(
066 PropsUtil.get(PropsKeys.MODEL_HINTS_CONFIGS));
067
068 for (String config : configs) {
069 if (config.startsWith("classpath*:")) {
070 String name = config.substring("classpath*:".length());
071
072 Enumeration<URL> enu = classLoader.getResources(name);
073
074 if (_log.isDebugEnabled() && !enu.hasMoreElements()) {
075 _log.debug("No resources found for " + name);
076 }
077
078 while (enu.hasMoreElements()) {
079 URL url = enu.nextElement();
080
081 if (_log.isDebugEnabled()) {
082 _log.debug("Loading " + name + " from " + url);
083 }
084
085 InputStream inputStream = url.openStream();
086
087 read(classLoader, url.toString(), inputStream);
088 }
089 }
090 else {
091 read(classLoader, config);
092 }
093 }
094 }
095 catch (Exception e) {
096 _log.error(e, e);
097 }
098 }
099
100 public String buildCustomValidatorName(String validatorName) {
101 return validatorName.concat(StringPool.UNDERLINE).concat(
102 PwdGenerator.getPassword(PwdGenerator.KEY3, 4));
103 }
104
105 public Map<String, String> getDefaultHints(String model) {
106 return _defaultHints.get(model);
107 }
108
109 public com.liferay.portal.kernel.xml.Element getFieldsEl(
110 String model, String field) {
111
112 Map<String, Object> fields = (Map<String, Object>)_modelFields.get(
113 model);
114
115 if (fields == null) {
116 return null;
117 }
118 else {
119 Element fieldsEl = (Element)fields.get(field + _ELEMENTS_SUFFIX);
120
121 if (fieldsEl == null) {
122 return null;
123 }
124 else {
125 return fieldsEl;
126 }
127 }
128 }
129
130 public Map<String, String> getHints(String model, String field) {
131 Map<String, Object> fields = (Map<String, Object>)_modelFields.get(
132 model);
133
134 if (fields == null) {
135 return null;
136 }
137 else {
138 return (Map<String, String>)fields.get(field + _HINTS_SUFFIX);
139 }
140 }
141
142 public int getMaxLength(String model, String field) {
143 Map<String, String> hints = getHints(model, field);
144
145 if (hints == null) {
146 return Integer.MAX_VALUE;
147 }
148
149 int maxLength = GetterUtil.getInteger(
150 ModelHintsConstants.TEXT_MAX_LENGTH);
151
152 maxLength = GetterUtil.getInteger(hints.get("max-length"), maxLength);
153
154 return maxLength;
155 }
156
157 public List<String> getModels() {
158 return ListUtil.fromCollection(_models);
159 }
160
161 public Tuple getSanitizeTuple(String model, String field) {
162 Map<String, Object> fields = (Map<String, Object>)_modelFields.get(
163 model);
164
165 if (fields == null) {
166 return null;
167 }
168 else {
169 return (Tuple)fields.get(field + _SANITIZE_SUFFIX);
170 }
171 }
172
173 public List<Tuple> getSanitizeTuples(String model) {
174 Map<String, Object> fields = (Map<String, Object>)_modelFields.get(
175 model);
176
177 if (fields == null) {
178 return Collections.emptyList();
179 }
180 else {
181 List<Tuple> sanitizeTuples = new ArrayList<Tuple>();
182
183 for (Map.Entry<String, Object> entry : fields.entrySet()) {
184 String key = entry.getKey();
185
186 if (key.endsWith(_SANITIZE_SUFFIX)) {
187 Tuple sanitizeTuple = (Tuple)entry.getValue();
188
189 sanitizeTuples.add(sanitizeTuple);
190 }
191 }
192
193 return sanitizeTuples;
194 }
195 }
196
197 public String getType(String model, String field) {
198 Map<String, Object> fields = (Map<String, Object>)_modelFields.get(
199 model);
200
201 if (fields == null) {
202 return null;
203 }
204 else {
205 return (String)fields.get(field + _TYPE_SUFFIX);
206 }
207 }
208
209 public List<Tuple> getValidators(String model, String field) {
210 Map<String, Object> fields = (Map<String, Object>)_modelFields.get(
211 model);
212
213 if ((fields == null) ||
214 (fields.get(field + _VALIDATORS_SUFFIX) == null)) {
215
216 return null;
217 }
218 else {
219 return (List<Tuple>)fields.get(field + _VALIDATORS_SUFFIX);
220 }
221 }
222
223 public String getValue(
224 String model, String field, String name, String defaultValue) {
225
226 Map<String, String> hints = getHints(model, field);
227
228 if (hints == null) {
229 return defaultValue;
230 }
231
232 return GetterUtil.getString(hints.get(name), defaultValue);
233 }
234
235 public boolean isCustomValidator(String validatorName) {
236 if (validatorName.equals("custom")) {
237 return true;
238 }
239
240 return false;
241 }
242
243 public boolean isLocalized(String model, String field) {
244 Map<String, Object> fields = (Map<String, Object>)_modelFields.get(
245 model);
246
247 if (fields == null) {
248 return false;
249 }
250 else {
251 Boolean localized = (Boolean)fields.get(
252 field + _LOCALIZATION_SUFFIX);
253
254 if (localized != null) {
255 return localized;
256 }
257 else {
258 return false;
259 }
260 }
261 }
262
263 public void read(ClassLoader classLoader, String source) throws Exception {
264 read(classLoader, source, classLoader.getResourceAsStream(source));
265 }
266
267 public void read(
268 ClassLoader classLoader, String source, InputStream inputStream)
269 throws Exception {
270
271 if (inputStream == null) {
272 if (_log.isWarnEnabled()) {
273 _log.warn("Cannot load " + source);
274 }
275
276 return;
277 }
278 else {
279 if (_log.isDebugEnabled()) {
280 _log.debug("Loading " + source);
281 }
282 }
283
284 Document document = _saxReader.read(inputStream);
285
286 Element rootElement = document.getRootElement();
287
288 List<Element> rootElements = rootElement.elements("hint-collection");
289
290 for (Element hintCollectionElement : rootElements) {
291 String name = hintCollectionElement.attributeValue("name");
292
293 Map<String, String> hints = _hintCollections.get(name);
294
295 if (hints == null) {
296 hints = new HashMap<String, String>();
297
298 _hintCollections.put(name, hints);
299 }
300
301 List<Element> hintElements = hintCollectionElement.elements("hint");
302
303 for (Element hintElement : hintElements) {
304 String hintName = hintElement.attributeValue("name");
305 String hintValue = hintElement.getText();
306
307 hints.put(hintName, hintValue);
308 }
309 }
310
311 rootElements = rootElement.elements("model");
312
313 for (Element modelElement : rootElements) {
314 String name = modelElement.attributeValue("name");
315
316 if (classLoader != ModelHintsImpl.class.getClassLoader()) {
317 ClassNameLocalServiceUtil.getClassName(name);
318 }
319
320 Map<String, String> defaultHints = new HashMap<String, String>();
321
322 _defaultHints.put(name, defaultHints);
323
324 Element defaultHintsElement = modelElement.element("default-hints");
325
326 if (defaultHintsElement != null) {
327 List<Element> hintElements = defaultHintsElement.elements(
328 "hint");
329
330 for (Element hintElement : hintElements) {
331 String hintName = hintElement.attributeValue("name");
332 String hintValue = hintElement.getText();
333
334 defaultHints.put(hintName, hintValue);
335 }
336 }
337
338 Map<String, Object> fields = (Map<String, Object>)_modelFields.get(
339 name);
340
341 if (fields == null) {
342 fields = new LinkedHashMap<String, Object>();
343
344 _modelFields.put(name, fields);
345 }
346
347 _models.add(name);
348
349 List<Element> modelElements = modelElement.elements("field");
350
351 for (Element fieldElement : modelElements) {
352 String fieldName = fieldElement.attributeValue("name");
353 String fieldType = fieldElement.attributeValue("type");
354 boolean fieldLocalized = GetterUtil.getBoolean(
355 fieldElement.attributeValue("localized"));
356
357 Map<String, String> fieldHints = new HashMap<String, String>();
358
359 fieldHints.putAll(defaultHints);
360
361 List<Element> fieldElements = fieldElement.elements(
362 "hint-collection");
363
364 for (Element hintCollectionElement : fieldElements) {
365 Map<String, String> hints = _hintCollections.get(
366 hintCollectionElement.attributeValue("name"));
367
368 fieldHints.putAll(hints);
369 }
370
371 fieldElements = fieldElement.elements("hint");
372
373 for (Element hintElement : fieldElements) {
374 String hintName = hintElement.attributeValue("name");
375 String hintValue = hintElement.getText();
376
377 fieldHints.put(hintName, hintValue);
378 }
379
380 Tuple fieldSanitize = null;
381
382 Element sanitizeElement = fieldElement.element("sanitize");
383
384 if (sanitizeElement != null) {
385 String contentType = sanitizeElement.attributeValue(
386 "content-type");
387 String modes = sanitizeElement.attributeValue("modes");
388
389 fieldSanitize = new Tuple(fieldName, contentType, modes);
390 }
391
392 Map<String, Tuple> fieldValidators =
393 new TreeMap<String, Tuple>();
394
395 fieldElements = fieldElement.elements("validator");
396
397 for (Element validatorElement : fieldElements) {
398 String validatorName = validatorElement.attributeValue(
399 "name");
400
401 if (Validator.isNull(validatorName)) {
402 continue;
403 }
404
405 String validatorErrorMessage = GetterUtil.getString(
406 validatorElement.attributeValue("error-message"));
407 String validatorValue = GetterUtil.getString(
408 validatorElement.getText());
409 boolean customValidator = isCustomValidator(validatorName);
410
411 if (customValidator) {
412 validatorName = buildCustomValidatorName(validatorName);
413 }
414
415 Tuple fieldValidator = new Tuple(
416 fieldName, validatorName, validatorErrorMessage,
417 validatorValue, customValidator);
418
419 fieldValidators.put(validatorName, fieldValidator);
420 }
421
422 fields.put(fieldName + _ELEMENTS_SUFFIX, fieldElement);
423 fields.put(fieldName + _TYPE_SUFFIX, fieldType);
424 fields.put(fieldName + _LOCALIZATION_SUFFIX, fieldLocalized);
425 fields.put(fieldName + _HINTS_SUFFIX, fieldHints);
426
427 if (fieldSanitize != null) {
428 fields.put(fieldName + _SANITIZE_SUFFIX, fieldSanitize);
429 }
430
431 if (!fieldValidators.isEmpty()) {
432 fields.put(
433 fieldName + _VALIDATORS_SUFFIX,
434 ListUtil.fromMapValues(fieldValidators));
435 }
436 }
437 }
438 }
439
440 public void setSAXReader(SAXReader saxReader) {
441 _saxReader = saxReader;
442 }
443
444 public String trimString(String model, String field, String value) {
445 if (value == null) {
446 return value;
447 }
448
449 int maxLength = getMaxLength(model, field);
450
451 if (value.length() > maxLength) {
452 return value.substring(0, maxLength);
453 }
454 else {
455 return value;
456 }
457 }
458
459 private static final String _ELEMENTS_SUFFIX = "_ELEMENTS";
460
461 private static final String _HINTS_SUFFIX = "_HINTS";
462
463 private static final String _LOCALIZATION_SUFFIX = "_LOCALIZATION";
464
465 private static final String _SANITIZE_SUFFIX = "_SANITIZE_SUFFIX";
466
467 private static final String _TYPE_SUFFIX = "_TYPE";
468
469 private static final String _VALIDATORS_SUFFIX = "_VALIDATORS";
470
471 private static Log _log = LogFactoryUtil.getLog(ModelHintsImpl.class);
472
473 private Map<String, Map<String, String>> _defaultHints;
474 private Map<String, Map<String, String>> _hintCollections;
475 private Map<String, Object> _modelFields;
476 private Set<String> _models;
477 private SAXReader _saxReader;
478
479 }