package frostillicus.xsp.model; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.SortedSet; import java.util.TreeSet; import javax.faces.application.FacesMessage; import javax.faces.context.FacesContext; import org.openntf.domino.Database; import org.openntf.domino.design.DatabaseDesign; import org.openntf.domino.design.FacesConfig; import com.ibm.commons.util.StringUtil; import frostillicus.xsp.bean.ManagedBean; import frostillicus.xsp.util.FrameworkUtils; /** * @since 1.0 */ public enum ModelUtils { ; public static Map<String, Object> getCacheScope() { Map<String, Object> scope = FrameworkUtils.getViewScope(); return scope == null ? new HashMap<String, Object>() : scope; } public static boolean isUnid(final String value) { if (value.length() != 32) { return false; } return isHex(value); } public static boolean isHex(final String value) { String chk = value.trim().toLowerCase(); for (int i = 0; i < chk.length(); i++) { char c = chk.charAt(i); boolean isHexDigit = Character.isDigit(c) || Character.isWhitespace(c) || c == 'a' || c == 'b' || c == 'c' || c == 'd' || c == 'e' || c == 'f'; if (!isHexDigit) { return false; } } return true; } public static void publishException(final Exception e) { FacesContext facesContext = FacesContext.getCurrentInstance(); if(facesContext != null) { StringWriter out = new StringWriter(); PrintWriter outWriter = new PrintWriter(out); e.printStackTrace(outWriter); outWriter.flush(); FacesMessage message = new FacesMessage(out.toString()); message.setSeverity(FacesMessage.SEVERITY_ERROR); facesContext.addMessage("", message); } else { if(e instanceof RuntimeException) { throw (RuntimeException)e; } else { throw new RuntimeException(e); } } } /** * * @param database * The database to search for the model objects * @param managerName * Either the name of a Manager by class or managed bean name or the name of a Model class * @return * A Class object representing a Manager for the given name, or null if not found */ @SuppressWarnings("unchecked") public static Class<? extends ModelManager<?>> findModelManager(final Database database, final String managerName) { if(StringUtil.isEmpty(managerName)) { return null; } DatabaseDesign design = database.getDesign(); ClassLoader loader; if(FrameworkUtils.isFaces()) { loader = FacesContext.getCurrentInstance().getContextClassLoader(); } else { loader = design.getDatabaseClassLoader(Thread.currentThread().getContextClassLoader()); } // First, see if we're dealing with a class name or bean name Class<?> referencedClass = null; if(managerName.contains(".")) { try { referencedClass = loader.loadClass(managerName); if(ModelManager.class.isAssignableFrom(referencedClass)) { // Then we're done immediately return (Class<? extends ModelManager<?>>)referencedClass; } // Otherwise, keep the referenced class around in case it's a model object } catch(ClassNotFoundException cnfe) { // Though we're likely doomed at this point, soldier on to the later tests } } // Now, search through the classes in the DB for any @ManagedBean-annotated classes that match for(String className : design.getJavaResourceClassNames()) { try { Class<?> loadedClass = loader.loadClass(className); if(isManager(loadedClass, managerName, referencedClass)) { return (Class<? extends ModelManager<?>>)loadedClass; } } catch(ClassNotFoundException cnfe) { // This happens when the note in the NSF contains an old class name - ignore } } // Now, look through faces-config-declared managed beans FacesConfig facesConfig = design.getFacesConfig(); if(facesConfig != null) { for(FacesConfig.ManagedBean bean : facesConfig.getManagedBeans()) { if(StringUtil.isNotEmpty(bean.getClassName())) { try { Class<?> loadedClass = loader.loadClass(bean.getClassName()); if(isManager(loadedClass, managerName, referencedClass)) { return (Class<? extends ModelManager<?>>)loadedClass; } } catch(ClassNotFoundException cnfe) { // This would be a config problem for the app, but we don't care here } } } } return null; } private static boolean isManager(final Class<?> loadedClass, final String managerName, final Class<?> referencedClass) { // There are two ways to identify the manager: by bean name or by an @ManagerFor annotation for a model class name // Check the bean name first ManagedBean beanAnnotation = loadedClass.getAnnotation(ManagedBean.class); if(beanAnnotation != null) { if(managerName.equals(beanAnnotation.name())) { if(ModelManager.class.isAssignableFrom(loadedClass)) { return true; } else { return false; } } } // Now check for a @ManagerFor annotation with the referenced class or bean name ManagerFor manFor = loadedClass.getAnnotation(ManagerFor.class); if(manFor != null) { if(referencedClass != null && referencedClass.equals(manFor.value())) { return true; } else if(managerName.equals(manFor.name())) { return true; } } return false; } // TODO integrate this with findModelManager @SuppressWarnings("unchecked") public static ModelManager<?> findManagerInstance(final FacesContext context, final String managerName) throws IOException { if(managerName == null) { return null; } Object managerObject = FrameworkUtils.resolveVariable(managerName); if(managerObject != null && !(managerObject instanceof ModelManager)) { throw new IllegalArgumentException("managerObject must be an instance of " + ModelManager.class.getName()); } // If the object is null, assume that the managerName is a class name and instantiate anew if(managerObject == null) { try { Class<ModelManager<?>> managerClass = (Class<ModelManager<?>>)FacesContext.getCurrentInstance().getContextClassLoader().loadClass(managerName); managerObject = managerClass.newInstance(); } catch(ClassNotFoundException cnfe) { IOException ioe = new IOException("Error while instantiating manager object for name '" + managerName + "'"); ioe.initCause(cnfe); throw ioe; } catch(InstantiationException ie) { IOException ioe = new IOException("Error while instantiating manager object for name '" + managerName + "'"); ioe.initCause(ie); throw ioe; } catch(IllegalAccessException iae) { IOException ioe = new IOException("Error while instantiating manager object for name '" + managerName + "'"); ioe.initCause(iae); throw ioe; } } return (ModelManager<?>)managerObject; } public static SortedSet<String> stringSet(final Collection<String> input) { SortedSet<String> result = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER); if(input != null) { result.addAll(input); } return result; } }