/* * Copyright 2001-2008 Geert Bevin (gbevin[remove] at uwyn dot com) * Licensed under the Apache License, Version 2.0 (the "License") * $Id: ElementInjector.java 3918 2008-04-14 17:35:35Z gbevin $ */ package com.uwyn.rife.engine; import com.uwyn.rife.engine.exceptions.*; import com.uwyn.rife.tools.BeanPropertyProcessor; import com.uwyn.rife.tools.BeanUtils; import com.uwyn.rife.tools.Convert; import com.uwyn.rife.tools.exceptions.BeanUtilsException; import com.uwyn.rife.tools.exceptions.ConversionException; import java.beans.PropertyDescriptor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; class ElementInjector { private ElementContext mContext = null; private ElementSupport mElement = null; private ElementAware mElementAware = null; private ElementInfo mElementInfo = null; private Map<String, Method> mPropertySetters = null; private Map<String, Method> mIncookieSetters = null; private Map<String, Method> mInputSetters = null; private Map<String, Method> mInbeanSetters = null; private SubmissionSettersCache mSubmissionSettersCache = null; ElementInjector(ElementContext context) { assert context != null; mContext = context; mElement = mContext.getElementSupport(); mElementAware = mElement.getElementAware(); mElementInfo = context.getElementInfo(); // try to obtain the element's setter methods from the cache mPropertySetters = mElementInfo.getSite().getCachedPropertySetters(mElementInfo.getId()); mIncookieSetters = mElementInfo.getSite().getCachedIncookieSetters(mElementInfo.getId()); mInputSetters = mElementInfo.getSite().getCachedInputSetters(mElementInfo.getId()); mInbeanSetters = mElementInfo.getSite().getCachedInbeanSetters(mElementInfo.getId()); mSubmissionSettersCache = mElementInfo.getSite().getSubmissionSettersCache(mElementInfo.getId()); // if at least one of the setter types couldn't be obtained, re-detect them all if (null == mPropertySetters || null == mIncookieSetters || null == mInputSetters || null == mInbeanSetters || null == mSubmissionSettersCache) { try { if (null == mSubmissionSettersCache) { mSubmissionSettersCache = new SubmissionSettersCache(); } BeanUtils.processProperties(BeanUtils.SETTERS, mElementAware.getClass(), null, null, null, new ElementInjectorPropertyProcessor()); if (null == mPropertySetters) { mPropertySetters = Collections.EMPTY_MAP; } if (null == mIncookieSetters) { mIncookieSetters = Collections.EMPTY_MAP; } if (null == mInputSetters) { mInputSetters = Collections.EMPTY_MAP; } if (null == mInbeanSetters) { mInbeanSetters = Collections.EMPTY_MAP; } // store the this element's setters in the cache mElementInfo.getSite().putCachedPropertySetters(mElementInfo.getId(), mPropertySetters); mElementInfo.getSite().putCachedIncookieSetters(mElementInfo.getId(), mIncookieSetters); mElementInfo.getSite().putCachedInputSetters(mElementInfo.getId(), mInputSetters); mElementInfo.getSite().putCachedInbeanSetters(mElementInfo.getId(), mInbeanSetters); mElementInfo.getSite().putSubmissionSettersCache(mElementInfo.getId(), mSubmissionSettersCache); } catch (BeanUtilsException e) { throw new ElementInjectionException(mElementInfo.getDeclarationName(), mElementAware.getClass(), e); } } } void performInjection(String submissionName) { Submission submission = null; if (submissionName != null) { submission = mElementInfo.getSubmission(submissionName); } // inject the element properties for (Map.Entry<String, Method> setter : mPropertySetters.entrySet()) { Method write = setter.getValue(); Class type = write.getParameterTypes()[0]; try { write.invoke(mElementAware, Convert.toType(mElementInfo.getProperty(setter.getKey()), type)); } catch (Exception e) { throw new PropertyInjectionException(mElementInfo.getDeclarationName(), mElementAware.getClass(), setter.getKey(), e); } } // inject the element parameters vars if (submission != null) { Map<String, Method> param_setters = mSubmissionSettersCache.getCachedSubmissionparamSetters(submissionName); if (param_setters != null) { for (Map.Entry<String, Method> setter : param_setters.entrySet()) { Method write = setter.getValue(); Class type = write.getParameterTypes()[0]; try { if (type.isArray()) { String[] values = mElement.getParameterValues(setter.getKey()); if (values != null) { write.invoke(mElementAware, new Object[] {Convert.toType(values, type)}); } } else { String value = mElement.getParameter(setter.getKey()); if (value != null) { write.invoke(mElementAware, new Object[] {Convert.toType(value, type)}); } } } catch (ConversionException e) { try { String[] values = submission.getParameterDefaultValues(setter.getKey()); if (values != null && type.isArray()) { if (values != null) { write.invoke(mElementAware, new Object[] {Convert.toType(values, type)}); } } else if (values != null && values.length > 0) { String value = values[0]; if (value != null) { write.invoke(mElementAware, new Object[] {Convert.toType(value, type)}); } } else if (!type.isPrimitive()) { write.invoke(mElementAware, new Object[] {null}); } } catch (Exception e2) { throw new ParameterInjectionException(mElementInfo.getDeclarationName(), mElementAware.getClass(), submissionName, setter.getKey(), e2); } } catch (Exception e) { throw new ParameterInjectionException(mElementInfo.getDeclarationName(), mElementAware.getClass(), submissionName, setter.getKey(), e); } } } } // inject the element incookies and global cookies for (Map.Entry<String, Method> setter : mIncookieSetters.entrySet()) { Method write = setter.getValue(); Class type = write.getParameterTypes()[0]; try { write.invoke(mElementAware, new Object[] {Convert.toType(mElement.getCookieValue(setter.getKey()), type)}); } catch (ConversionException e) { try { String value = mElementInfo.getIncookieDefaultValue(setter.getKey()); if (value != null) { write.invoke(mElementAware, new Object[] {Convert.toType(value, type)}); } else if (!type.isPrimitive()) { write.invoke(mElementAware, new Object[] {null}); } } catch (Exception e2) { throw new IncookieInjectionException(mElementInfo.getDeclarationName(), mElementAware.getClass(), setter.getKey(), e2); } } catch (Exception e) { throw new IncookieInjectionException(mElementInfo.getDeclarationName(), mElementAware.getClass(), setter.getKey(), e); } } // inject the element inputs and global vars for (Map.Entry<String, Method> setter : mInputSetters.entrySet()) { Method write = setter.getValue(); Class type = write.getParameterTypes()[0]; try { if (type.isArray()) { write.invoke(mElementAware, new Object[] {Convert.toType(mElement.getInputValues(setter.getKey()), type)}); } else { write.invoke(mElementAware, new Object[] {Convert.toType(mElement.getInput(setter.getKey()), type)}); } } catch (ConversionException e) { try { String[] values = mElementInfo.getInputDefaultValues(setter.getKey()); if (values != null && type.isArray()) { if (values != null) { write.invoke(mElementAware, new Object[] {Convert.toType(values, type)}); } } else if (values != null && values.length > 0) { String value = values[0]; if (value != null) { write.invoke(mElementAware, new Object[] {Convert.toType(value, type)}); } } else if (!type.isPrimitive()) { write.invoke(mElementAware, new Object[] {null}); } } catch (Exception e2) { throw new InputInjectionException(mElementInfo.getDeclarationName(), mElementAware.getClass(), setter.getKey(), e2); } } catch (Exception e) { throw new InputInjectionException(mElementInfo.getDeclarationName(), mElementAware.getClass(), setter.getKey(), e); } } // inject the element named inbeans for (Map.Entry<String, Method> setter : mInbeanSetters.entrySet()) { Method write = setter.getValue(); Class type = write.getParameterTypes()[0]; try { write.invoke(mElementAware, new Object[] {Convert.toType(mElement.getNamedInputBean(setter.getKey()), type)}); } catch (Exception e) { throw new NamedInbeanInjectionException(mElementInfo.getDeclarationName(), mElementAware.getClass(), setter.getKey(), e); } } // inject the element named submission beans if (submission != null) { Map<String, Method> bean_setters = mSubmissionSettersCache.getCachedSubmissionbeanSetters(submissionName); if (bean_setters != null) { for (Map.Entry<String, Method> setter : bean_setters.entrySet()) { Method write = setter.getValue(); Class type = write.getParameterTypes()[0]; try { write.invoke(mElementAware, new Object[] {Convert.toType(mElement.getNamedSubmissionBean(submissionName, setter.getKey()), type)}); } catch (Exception e) { throw new NamedSubmissionBeanInjectionException(mElementInfo.getDeclarationName(), mElementAware.getClass(), setter.getKey(), e); } } } // inject the element submission file uploads Map<String, Method> file_setters = mSubmissionSettersCache.getCachedUploadedfileSetters(submissionName); if (file_setters != null) { for (Map.Entry<String, Method> setter : file_setters.entrySet()) { Method write = setter.getValue(); UploadedFile file = mContext.getUploadedFile(setter.getKey()); if (file != null) { try { write.invoke(mElementAware, new Object[] {file}); } catch (Exception e) { throw new UploadedSubmissionFilesInjectionException(mElementInfo.getDeclarationName(), mElementAware.getClass(), setter.getKey(), e); } } } } } } private class ElementInjectorPropertyProcessor implements BeanPropertyProcessor { private Collection<String> mPropertynames; private Collection<String> mNamesIncookies; private Collection<String> mNamesInputs; private Collection<String> mNamesInbeans; ElementInjectorPropertyProcessor() { mPropertynames = mElementInfo.getInjectablePropertyNames(); if (!mElementInfo.hasIncookies() && !mElementInfo.hasGlobalCookies()) { mNamesIncookies = null; } else { final Collection<String> names_globalcookies = mElementInfo.getGlobalCookieNames(); if (names_globalcookies != null && names_globalcookies.size() > 0) { mNamesIncookies = new ArrayList<String>(mElementInfo.getIncookieNames()); mNamesIncookies.addAll(names_globalcookies); } else { mNamesIncookies = mElementInfo.getIncookieNames(); } } if (!mElementInfo.hasInputs() && !mElementInfo.hasGlobalVars()) { mNamesInputs = null; } else { Collection<String> names_globalvars = mElementInfo.getGlobalVarNames(); if (names_globalvars != null && names_globalvars.size() > 0) { mNamesInputs = new ArrayList<String>(mElementInfo.getInputNames()); mNamesInputs.addAll(names_globalvars); } else { mNamesInputs = mElementInfo.getInputNames(); } } if (mElementInfo.hasNamedInbeans()) { mNamesInbeans = mElementInfo.getNamedInbeanNames(); } else { mNamesInbeans = null; } } public boolean gotProperty(String name, PropertyDescriptor descriptor) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { Method write = descriptor.getWriteMethod(); Class type = write.getParameterTypes()[0]; // detect the element properties if (mPropertynames != null && mPropertynames.contains(name)) { if (null == mPropertySetters) { mPropertySetters = new LinkedHashMap<String, Method>(); } write.setAccessible(true); mPropertySetters.put(name, write); } // detect the element incookies and global cookies else if (mNamesIncookies != null && mNamesIncookies.contains(name)) { if (null == mIncookieSetters) { mIncookieSetters = new LinkedHashMap<String, Method>(); } write.setAccessible(true); mIncookieSetters.put(name, write); } // detect the element inputs and global vars else if (mNamesInputs != null && mNamesInputs.contains(name)) { if (null == mInputSetters) { mInputSetters = new LinkedHashMap<String, Method>(); } write.setAccessible(true); mInputSetters.put(name, write); } // detect the element named inbeans else if (mNamesInbeans != null && mNamesInbeans.contains(name)) { if (null == mInbeanSetters) { mInbeanSetters = new LinkedHashMap<String, Method>(); } write.setAccessible(true); mInbeanSetters.put(name, write); } else { for (Submission submission : mElementInfo.getSubmissions()) { if (submission.containsParameter(name)) { Map<String, Method> param_setters = mSubmissionSettersCache.getCachedSubmissionparamSetters(submission.getName()); if (null == param_setters) { param_setters = new LinkedHashMap<String, Method>(); mSubmissionSettersCache.putCachedSubmissionparamSetters(submission.getName(), param_setters); } write.setAccessible(true); param_setters.put(name, write); } else if (submission.containsNamedBean(name)) { Map<String, Method> bean_setters = mSubmissionSettersCache.getCachedSubmissionbeanSetters(submission.getName()); if (null == bean_setters) { bean_setters = new LinkedHashMap<String, Method>(); mSubmissionSettersCache.putCachedSubmissionbeanSetters(submission.getName(), bean_setters); } write.setAccessible(true); bean_setters.put(name, write); } else if (submission.containsFile(name) && UploadedFile.class.isAssignableFrom(type)) { Map<String, Method> file_setters = mSubmissionSettersCache.getCachedUploadedfileSetters(submission.getName()); if (null == file_setters) { file_setters = new LinkedHashMap<String, Method>(); mSubmissionSettersCache.putCachedUploadedfileSetters(submission.getName(), file_setters); } write.setAccessible(true); file_setters.put(name, write); } } } return true; } } }