/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.myfaces.tobago.util;
import org.apache.commons.beanutils.ConstructorUtils;
import org.apache.myfaces.tobago.application.LabelValueBindingFacesMessage;
import org.apache.myfaces.tobago.application.LabelValueExpressionFacesMessage;
import org.apache.myfaces.tobago.compat.FacesUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.event.ExceptionQueuedEvent;
import javax.faces.event.ExceptionQueuedEventContext;
import javax.faces.event.PhaseId;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
/**
* Utility to create and add {@link FacesMessage} object to the context.
* The message will be internationalized with a bundle in the following order:
* <ol>
* <li>Application bundle</li>
* <li>Tobago bundle</li>
* <li>Default JSF bundle</li>
* </ol>
*/
public class MessageUtils {
private static final Logger LOG = LoggerFactory.getLogger(MessageUtils.class);
private static final String DETAIL_SUFFIX = "_detail";
public static void addMessage(
FacesContext facesContext, UIComponent component, FacesMessage.Severity severity,
String messageId, Object[] args) {
facesContext.addMessage(component.getClientId(facesContext),
getMessage(facesContext, facesContext.getViewRoot().getLocale(), severity, messageId, args));
}
public static FacesMessage getMessage(
FacesContext facesContext, Locale locale,
FacesMessage.Severity severity, String messageId, Object... args) {
ResourceBundle appBundle = getApplicationBundle(facesContext, locale);
String summary = getBundleString(appBundle, messageId);
String detail = getBundleString(appBundle, messageId + DETAIL_SUFFIX);
if (summary == null || detail == null) {
ResourceBundle tobagoBundle = getTobagoBundle();
if (summary == null) {
summary = getBundleString(tobagoBundle, messageId);
}
if (detail == null) {
detail = getBundleString(tobagoBundle, messageId + DETAIL_SUFFIX);
}
if (summary == null || detail == null) {
ResourceBundle defBundle = getDefaultBundle(facesContext, locale);
if (summary == null) {
summary = getBundleString(defBundle, messageId);
}
if (detail == null) {
detail = getBundleString(defBundle, messageId + DETAIL_SUFFIX);
}
}
}
if (summary == null && detail == null) {
//Neither detail nor summary found
facesContext.getExternalContext().log("No message with id " + messageId + " found in any bundle");
return new FacesMessage(severity, messageId, null);
}
if (FacesUtils.supportsEL()) {
if (args != null && args.length > 0) {
MessageFormat format;
if (summary != null) {
format = new MessageFormat(summary, locale);
summary = format.format(args);
}
if (detail != null) {
format = new MessageFormat(detail, locale);
detail = format.format(args);
}
}
return new LabelValueExpressionFacesMessage(severity, summary, detail);
} else {
return new LabelValueBindingFacesMessage(severity, summary, detail, locale, args);
}
}
private static String getBundleString(ResourceBundle bundle, String key) {
try {
return bundle == null ? null : bundle.getString(key);
} catch (MissingResourceException e) {
return null;
}
}
private static ResourceBundle getApplicationBundle(FacesContext facesContext, Locale locale) {
String bundleName = facesContext.getApplication().getMessageBundle();
return bundleName != null ? getBundle(facesContext, locale, bundleName) : null;
}
private static ResourceBundle getTobagoBundle() {
// XXX This is ugly, can be removed after merging tobago-jsf-compat to tobago-core
try {
Class clazz = Class.forName("org.apache.myfaces.tobago.context.TobagoResourceBundle");
Object bundle = ConstructorUtils.invokeConstructor(clazz, new Object[0]);
return (ResourceBundle) bundle;
} catch (Exception e) {
LOG.error("Can't create TobagoResourceBundle, but it should be in the core.", e);
return null; // should not be possible.
}
}
private static ResourceBundle getDefaultBundle(FacesContext facesContext, Locale locale) {
return getBundle(facesContext, locale, FacesMessage.FACES_MESSAGES);
}
private static ResourceBundle getBundle(FacesContext facesContext, Locale locale, String bundleName) {
try {
return ResourceBundle.getBundle(bundleName, locale, MessageUtils.class.getClassLoader());
} catch (MissingResourceException ignore2) {
try {
return ResourceBundle.getBundle(bundleName, locale, Thread.currentThread().getContextClassLoader());
} catch (MissingResourceException damned) {
facesContext.getExternalContext().log("resource bundle " + bundleName + " could not be found");
return null;
}
}
}
public static String getLabel(FacesContext facesContext, UIComponent component) {
Object label = component.getAttributes().get("label");
if (label != null) {
return label.toString();
}
if (FacesUtils.hasValueBindingOrValueExpression(component, "label")) {
return FacesUtils.getExpressionString(component, "label");
}
return component.getClientId(facesContext);
}
public static String getFormatedMessage(String message, Locale locale, Object... args) {
if (args != null && args.length > 0 && message != null) {
MessageFormat format = new MessageFormat(message, locale);
return format.format(args);
}
return message;
}
public static void handleExceptions(FacesContext facesContext) {
facesContext.getExceptionHandler().handle();
}
public static void publishException(Throwable e, PhaseId phaseId, FacesContext facesContext) {
ExceptionQueuedEventContext context = new ExceptionQueuedEventContext(facesContext, e, null, phaseId);
facesContext.getApplication().publishEvent(facesContext, ExceptionQueuedEvent.class, context);
}
}