PageRenderTime 43ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/myfaces_core-2.1.10/src/myfaces-impl-2.1.10-sources/org/apache/myfaces/config/ManagedBeanBuilder.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 723 lines | 546 code | 77 blank | 100 comment | 92 complexity | 0e5b526f7b39abfb0a512ddc737b2030 MD5 | raw file
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19. package org.apache.myfaces.config;
  20. import org.apache.commons.beanutils.PropertyUtils;
  21. import org.apache.myfaces.config.annotation.LifecycleProvider;
  22. import org.apache.myfaces.config.annotation.LifecycleProvider2;
  23. import org.apache.myfaces.config.annotation.LifecycleProviderFactory;
  24. import org.apache.myfaces.config.element.ListEntries;
  25. import org.apache.myfaces.config.element.ListEntry;
  26. import org.apache.myfaces.config.element.ManagedBean;
  27. import org.apache.myfaces.config.element.ManagedProperty;
  28. import org.apache.myfaces.config.element.MapEntries;
  29. import org.apache.myfaces.config.element.MapEntry;
  30. import org.apache.myfaces.context.servlet.StartupServletExternalContextImpl;
  31. import org.apache.myfaces.shared.util.ClassUtils;
  32. import org.apache.myfaces.util.ContainerUtils;
  33. import javax.el.ELContext;
  34. import javax.el.ELException;
  35. import javax.el.ELResolver;
  36. import javax.el.ExpressionFactory;
  37. import javax.el.ValueExpression;
  38. import javax.faces.FacesException;
  39. import javax.faces.application.Application;
  40. import javax.faces.application.ProjectStage;
  41. import javax.faces.context.ExternalContext;
  42. import javax.faces.context.FacesContext;
  43. import javax.naming.NamingException;
  44. import java.lang.reflect.Array;
  45. import java.lang.reflect.InvocationTargetException;
  46. import java.util.ArrayList;
  47. import java.util.Comparator;
  48. import java.util.HashMap;
  49. import java.util.Iterator;
  50. import java.util.List;
  51. import java.util.Map;
  52. import java.util.logging.Level;
  53. import java.util.logging.Logger;
  54. /**
  55. * Create and initialize managed beans
  56. *
  57. * @author <a href="mailto:oliver@rossmueller.com">Oliver Rossmueller</a> (latest modification by $Author: struberg $)
  58. * @author Anton Koinov
  59. */
  60. public class ManagedBeanBuilder
  61. {
  62. //private static Log log = LogFactory.getLog(ManagedBeanBuilder.class);
  63. private static Logger log = Logger.getLogger(ManagedBeanBuilder.class.getName());
  64. private RuntimeConfig _runtimeConfig;
  65. public final static String REQUEST = "request";
  66. public final static String VIEW = "view";
  67. public final static String APPLICATION = "application";
  68. public final static String SESSION = "session";
  69. public final static String NONE = "none";
  70. /**
  71. * Comparator used to compare Scopes in the following order:
  72. * REQUEST VIEW SESSION APPLICATION NONE
  73. * @author Jakob Korherr
  74. */
  75. private final static Comparator<String> SCOPE_COMPARATOR
  76. = new Comparator<String>()
  77. {
  78. public int compare(String o1, String o2)
  79. {
  80. if (o1.equalsIgnoreCase(o2))
  81. {
  82. // the same scope
  83. return 0;
  84. }
  85. if (o1.equalsIgnoreCase(NONE))
  86. {
  87. // none is greater than any other scope
  88. return 1;
  89. }
  90. if (o1.equalsIgnoreCase(APPLICATION))
  91. {
  92. if (o2.equalsIgnoreCase(NONE))
  93. {
  94. // application is smaller than none
  95. return -1;
  96. }
  97. else
  98. {
  99. // ..but greater than any other scope
  100. return 1;
  101. }
  102. }
  103. if (o1.equalsIgnoreCase(SESSION))
  104. {
  105. if (o2.equalsIgnoreCase(REQUEST) || o2.equalsIgnoreCase(VIEW))
  106. {
  107. // session is greater than request and view
  108. return 1;
  109. }
  110. else
  111. {
  112. // but smaller than any other scope
  113. return -1;
  114. }
  115. }
  116. if (o1.equalsIgnoreCase(VIEW))
  117. {
  118. if (o2.equalsIgnoreCase(REQUEST))
  119. {
  120. // view is greater than request
  121. return 1;
  122. }
  123. else
  124. {
  125. // ..but smaller than any other scope
  126. return -1;
  127. }
  128. }
  129. if (o1.equalsIgnoreCase(REQUEST))
  130. {
  131. // request is smaller than any other scope
  132. return -1;
  133. }
  134. // not a valid scope
  135. throw new IllegalArgumentException(o1 + " is not a valid scope");
  136. }
  137. };
  138. @SuppressWarnings("unchecked")
  139. public Object buildManagedBean(FacesContext facesContext, ManagedBean beanConfiguration) throws FacesException
  140. {
  141. try
  142. {
  143. ExternalContext externalContext = facesContext.getExternalContext();
  144. LifecycleProvider lifecycleProvider = LifecycleProviderFactory
  145. .getLifecycleProviderFactory( externalContext).getLifecycleProvider(externalContext);
  146. final Object bean = lifecycleProvider.newInstance(beanConfiguration.getManagedBeanClassName());
  147. switch (beanConfiguration.getInitMode())
  148. {
  149. case ManagedBean.INIT_MODE_PROPERTIES:
  150. try
  151. {
  152. initializeProperties(facesContext, beanConfiguration, bean);
  153. }
  154. catch (IllegalArgumentException e)
  155. {
  156. throw new IllegalArgumentException(
  157. e.getMessage()
  158. + " for bean '"
  159. + beanConfiguration.getManagedBeanName()
  160. + "' check the configuration to make sure all properties "
  161. + "correspond with get/set methods", e);
  162. }
  163. break;
  164. case ManagedBean.INIT_MODE_MAP:
  165. if (!(bean instanceof Map))
  166. {
  167. throw new IllegalArgumentException("Class " + bean.getClass().getName()
  168. + " of managed bean "
  169. + beanConfiguration.getManagedBeanName()
  170. + " is not a Map.");
  171. }
  172. initializeMap(facesContext, beanConfiguration.getMapEntries(), (Map<Object, Object>) bean);
  173. break;
  174. case ManagedBean.INIT_MODE_LIST:
  175. if (!(bean instanceof List))
  176. {
  177. throw new IllegalArgumentException("Class " + bean.getClass().getName()
  178. + " of managed bean "
  179. + beanConfiguration.getManagedBeanName()
  180. + " is not a List.");
  181. }
  182. initializeList(facesContext, beanConfiguration.getListEntries(), (List<Object>) bean);
  183. break;
  184. case ManagedBean.INIT_MODE_NO_INIT:
  185. // no init values
  186. break;
  187. default:
  188. throw new IllegalStateException("Unknown managed bean type "
  189. + bean.getClass().getName() + " for managed bean "
  190. + beanConfiguration.getManagedBeanName() + '.');
  191. }
  192. // MYFACES-1761 if implements LifecycleProvider,
  193. //PostConstruct was already called, but if implements
  194. //LifecycleProvider2, call it now.
  195. if (lifecycleProvider instanceof LifecycleProvider2)
  196. {
  197. ((LifecycleProvider2)lifecycleProvider).postConstruct(bean);
  198. }
  199. return bean;
  200. }
  201. catch (IllegalAccessException e)
  202. {
  203. throw new FacesException(e);
  204. }
  205. catch (InvocationTargetException e)
  206. {
  207. throw new FacesException(e);
  208. }
  209. catch (NamingException e)
  210. {
  211. throw new FacesException(e);
  212. }
  213. catch (ClassNotFoundException e)
  214. {
  215. throw new FacesException(e);
  216. }
  217. catch (InstantiationException e)
  218. {
  219. throw new FacesException(e);
  220. }
  221. }
  222. @SuppressWarnings("unchecked")
  223. private void initializeProperties(FacesContext facesContext,
  224. ManagedBean beanConfiguration, Object bean)
  225. {
  226. ELResolver elResolver = facesContext.getApplication().getELResolver();
  227. ELContext elContext = facesContext.getELContext();
  228. for (ManagedProperty property : beanConfiguration.getManagedProperties())
  229. {
  230. Object value = null;
  231. switch (property.getType())
  232. {
  233. case ManagedProperty.TYPE_LIST:
  234. // JSF 1.1, 5.3.1.3
  235. // Call the property getter, if it exists.
  236. // If the getter returns null or doesn't exist, create a java.util.ArrayList,
  237. // otherwise use the returned Object ...
  238. if (PropertyUtils.isReadable(bean, property.getPropertyName()))
  239. {
  240. value = elResolver.getValue(elContext, bean, property.getPropertyName());
  241. }
  242. value = value == null ? new ArrayList<Object>() : value;
  243. if (value instanceof List)
  244. {
  245. initializeList(facesContext, property.getListEntries(), (List<Object>)value);
  246. }
  247. else if (value != null && value.getClass().isArray())
  248. {
  249. int length = Array.getLength(value);
  250. ArrayList<Object> temp = new ArrayList<Object>(length);
  251. for (int i = 0; i < length; i++)
  252. {
  253. temp.add(Array.get(value, i));
  254. }
  255. initializeList(facesContext, property.getListEntries(), temp);
  256. value = Array.newInstance(value.getClass().getComponentType(), temp.size());
  257. length = temp.size();
  258. for (int i = 0; i < length; i++)
  259. {
  260. Array.set(value, i, temp.get(i));
  261. }
  262. }
  263. else
  264. {
  265. value = new ArrayList<Object>();
  266. initializeList(facesContext, property.getListEntries(), (List<Object>) value);
  267. }
  268. break;
  269. case ManagedProperty.TYPE_MAP:
  270. // JSF 1.1, 5.3.1.3
  271. // Call the property getter, if it exists.
  272. // If the getter returns null or doesn't exist, create a java.util.HashMap,
  273. // otherwise use the returned java.util.Map .
  274. if (PropertyUtils.isReadable(bean, property.getPropertyName()))
  275. {
  276. value = elResolver.getValue(elContext, bean, property.getPropertyName());
  277. }
  278. value = value == null ? new HashMap<Object, Object>() : value;
  279. if (!(value instanceof Map))
  280. {
  281. value = new HashMap<Object, Object>();
  282. }
  283. initializeMap(facesContext, property.getMapEntries(), (Map<Object, Object>) value);
  284. break;
  285. case ManagedProperty.TYPE_NULL:
  286. break;
  287. case ManagedProperty.TYPE_VALUE:
  288. // check for correct scope of a referenced bean
  289. if (!isInValidScope(facesContext, property, beanConfiguration))
  290. {
  291. throw new FacesException("Property " + property.getPropertyName() +
  292. " references object in a scope with shorter lifetime than the target scope " +
  293. beanConfiguration.getManagedBeanScope());
  294. }
  295. value = property.getRuntimeValue(facesContext);
  296. break;
  297. default:
  298. throw new FacesException("unknown ManagedProperty type: "+ property.getType());
  299. }
  300. Class<?> propertyClass = null;
  301. if (property.getPropertyClass() == null)
  302. {
  303. propertyClass = elResolver.getType(elContext, bean, property.getPropertyName());
  304. }
  305. else
  306. {
  307. propertyClass = ClassUtils.simpleJavaTypeToClass(property.getPropertyClass());
  308. }
  309. if (null == propertyClass)
  310. {
  311. throw new IllegalArgumentException("unable to find the type of property " + property.getPropertyName());
  312. }
  313. Object coercedValue = coerceToType(facesContext, value, propertyClass);
  314. elResolver.setValue(elContext, bean, property.getPropertyName(), coercedValue);
  315. }
  316. }
  317. // We no longer use the convertToType from shared impl because we switched
  318. // to unified EL in JSF 1.2
  319. @SuppressWarnings("unchecked")
  320. public static <T> T coerceToType(FacesContext facesContext, Object value, Class<? extends T> desiredClass)
  321. {
  322. if (value == null)
  323. {
  324. return null;
  325. }
  326. try
  327. {
  328. ExpressionFactory expFactory = facesContext.getApplication().getExpressionFactory();
  329. // Use coersion implemented by JSP EL for consistency with EL
  330. // expressions. Additionally, it caches some of the coersions.
  331. return (T)expFactory.coerceToType(value, desiredClass);
  332. }
  333. catch (ELException e)
  334. {
  335. String message = "Cannot coerce " + value.getClass().getName()
  336. + " to " + desiredClass.getName();
  337. log.log(Level.SEVERE, message , e);
  338. throw new FacesException(message, e);
  339. }
  340. }
  341. /**
  342. * Checks if the scope of the property value is valid for a bean to be stored in targetScope.
  343. * If one of the scopes is a custom scope (since jsf 2.0), this method only checks the
  344. * references if the current ProjectStage is not Production.
  345. * @param facesContext
  346. * @param property the property to be checked
  347. * @param beanConfiguration the ManagedBean, which will be created
  348. */
  349. private boolean isInValidScope(FacesContext facesContext, ManagedProperty property, ManagedBean beanConfiguration)
  350. {
  351. if (!property.isValueReference())
  352. {
  353. // no value reference but a literal value -> nothing to check
  354. return true;
  355. }
  356. // get the targetScope (since 2.0 this could be an EL ValueExpression)
  357. String targetScope = null;
  358. if (beanConfiguration.isManagedBeanScopeValueExpression())
  359. {
  360. // the scope is a custom scope
  361. // Spec says, that the developer has to take care about the references
  362. // to and from managed-beans in custom scopes.
  363. // However, we do check the references, if we are not in Production stage
  364. if (facesContext.isProjectStage(ProjectStage.Production))
  365. {
  366. return true;
  367. }
  368. else
  369. {
  370. targetScope = getNarrowestScope(facesContext,
  371. beanConfiguration
  372. .getManagedBeanScopeValueExpression(facesContext)
  373. .getExpressionString());
  374. // if we could not obtain a targetScope, return true
  375. if (targetScope == null)
  376. {
  377. return true;
  378. }
  379. }
  380. }
  381. else
  382. {
  383. targetScope = beanConfiguration.getManagedBeanScope();
  384. if (targetScope == null)
  385. {
  386. targetScope = NONE;
  387. }
  388. }
  389. // optimization: 'request' scope can reference any value scope
  390. if (targetScope.equalsIgnoreCase(REQUEST))
  391. {
  392. return true;
  393. }
  394. String valueScope = getNarrowestScope(facesContext,
  395. property.getValueBinding(facesContext)
  396. .getExpressionString());
  397. // if we could not obtain a valueScope, return true
  398. if (valueScope == null)
  399. {
  400. return true;
  401. }
  402. // the target scope needs to have a shorter (or equal) lifetime than the value scope
  403. return (SCOPE_COMPARATOR.compare(targetScope, valueScope) <= 0);
  404. }
  405. /**
  406. * Gets the narrowest scope to which the ValueExpression points.
  407. * @param facesContext
  408. * @param valueExpression
  409. * @return
  410. */
  411. private String getNarrowestScope(FacesContext facesContext, String valueExpression)
  412. {
  413. List<String> expressions = extractExpressions(valueExpression);
  414. // exclude NONE scope, if there are more than one ValueExpressions (see Spec for details)
  415. String narrowestScope = expressions.size() == 1 ? NONE : APPLICATION;
  416. boolean scopeFound = false;
  417. for (String expression : expressions)
  418. {
  419. String valueScope = getScope(facesContext, expression);
  420. if (valueScope == null)
  421. {
  422. continue;
  423. }
  424. // we have found at least one valid scope at this point
  425. scopeFound = true;
  426. if (SCOPE_COMPARATOR.compare(valueScope, narrowestScope) < 0)
  427. {
  428. narrowestScope = valueScope;
  429. }
  430. }
  431. return scopeFound ? narrowestScope : null;
  432. }
  433. private String getScope(FacesContext facesContext, String expression)
  434. {
  435. String beanName = getFirstSegment(expression);
  436. ExternalContext externalContext = facesContext.getExternalContext();
  437. // check scope objects
  438. if (beanName.equalsIgnoreCase("requestScope"))
  439. {
  440. return REQUEST;
  441. }
  442. if (beanName.equalsIgnoreCase("sessionScope"))
  443. {
  444. return SESSION;
  445. }
  446. if (beanName.equalsIgnoreCase("applicationScope"))
  447. {
  448. return APPLICATION;
  449. }
  450. // check implicit objects
  451. if (beanName.equalsIgnoreCase("cookie"))
  452. {
  453. return REQUEST;
  454. }
  455. if (beanName.equalsIgnoreCase("facesContext"))
  456. {
  457. return REQUEST;
  458. }
  459. if (beanName.equalsIgnoreCase("header"))
  460. {
  461. return REQUEST;
  462. }
  463. if (beanName.equalsIgnoreCase("headerValues"))
  464. {
  465. return REQUEST;
  466. }
  467. if (beanName.equalsIgnoreCase("param"))
  468. {
  469. return REQUEST;
  470. }
  471. if (beanName.equalsIgnoreCase("paramValues"))
  472. {
  473. return REQUEST;
  474. }
  475. if (beanName.equalsIgnoreCase("request"))
  476. {
  477. return REQUEST;
  478. }
  479. if (beanName.equalsIgnoreCase("view")) // Spec says that view is considered to be in request scope
  480. {
  481. return REQUEST;
  482. }
  483. if (beanName.equalsIgnoreCase("application"))
  484. {
  485. return APPLICATION;
  486. }
  487. if (beanName.equalsIgnoreCase("initParam"))
  488. {
  489. return APPLICATION;
  490. }
  491. // not found so far - check all scopes
  492. final boolean startup = (externalContext instanceof StartupServletExternalContextImpl);
  493. if (!startup)
  494. {
  495. // request and session maps are only available at runtime - not at startup
  496. // (the following code would throw an UnsupportedOperationException).
  497. if (externalContext.getRequestMap().get(beanName) != null)
  498. {
  499. return REQUEST;
  500. }
  501. if (externalContext.getSessionMap().get(beanName) != null)
  502. {
  503. return SESSION;
  504. }
  505. }
  506. if (externalContext.getApplicationMap().get(beanName) != null)
  507. {
  508. return APPLICATION;
  509. }
  510. if (facesContext.getViewRoot().getViewMap().get(beanName) != null)
  511. {
  512. return VIEW;
  513. }
  514. //not found - check mangaged bean config
  515. ManagedBean mbc = getRuntimeConfig(facesContext).getManagedBean(beanName);
  516. if (mbc != null)
  517. {
  518. // managed-bean-scope could be a EL ValueExpression (since 2.0)
  519. if (mbc.isManagedBeanScopeValueExpression())
  520. {
  521. // the scope is a custom scope
  522. // Spec says, that the developer has to take care about the references
  523. // to and from managed-beans in custom scopes.
  524. // However, we do check the references, if we are not in Production stage
  525. if (facesContext.isProjectStage(ProjectStage.Production))
  526. {
  527. return null;
  528. }
  529. else
  530. {
  531. String scopeExpression = mbc.getManagedBeanScopeValueExpression(facesContext).getExpressionString();
  532. return getNarrowestScope(facesContext, scopeExpression);
  533. }
  534. }
  535. else
  536. {
  537. return mbc.getManagedBeanScope();
  538. }
  539. }
  540. return null;
  541. }
  542. /**
  543. * Extract the first expression segment, that is the substring up to the first '.' or '['
  544. *
  545. * @param expression
  546. * @return first segment of the expression
  547. */
  548. private String getFirstSegment(String expression)
  549. {
  550. int indexDot = expression.indexOf('.');
  551. int indexBracket = expression.indexOf('[');
  552. if (indexBracket < 0)
  553. {
  554. return indexDot < 0 ? expression : expression.substring(0, indexDot);
  555. }
  556. if (indexDot < 0)
  557. {
  558. return expression.substring(0, indexBracket);
  559. }
  560. return expression.substring(0, Math.min(indexDot, indexBracket));
  561. }
  562. private List<String> extractExpressions(String expressionString)
  563. {
  564. List<String> expressions = new ArrayList<String>();
  565. for (String expression : expressionString.split("\\#\\{"))
  566. {
  567. int index = expression.indexOf('}');
  568. if (index >= 0)
  569. {
  570. expressions.add(expression.substring(0, index));
  571. }
  572. }
  573. return expressions;
  574. }
  575. private void initializeMap(FacesContext facesContext, MapEntries mapEntries,
  576. Map<? super Object, ? super Object> map)
  577. {
  578. Application application = facesContext.getApplication();
  579. Class<?> keyClass = (mapEntries.getKeyClass() == null)
  580. ? String.class : ClassUtils.simpleJavaTypeToClass(mapEntries.getKeyClass());
  581. Class<?> valueClass = (mapEntries.getValueClass() == null)
  582. ? String.class : ClassUtils.simpleJavaTypeToClass(mapEntries.getValueClass());
  583. ValueExpression valueExpression;
  584. ExpressionFactory expFactory = application.getExpressionFactory();
  585. ELContext elContext = facesContext.getELContext();
  586. for (Iterator<? extends MapEntry> iterator = mapEntries.getMapEntries(); iterator.hasNext();)
  587. {
  588. MapEntry entry = iterator.next();
  589. Object key = entry.getKey();
  590. if (ContainerUtils.isValueReference((String) key))
  591. {
  592. valueExpression = expFactory.createValueExpression(elContext, (String) key, Object.class);
  593. key = valueExpression.getValue(elContext);
  594. }
  595. if (entry.isNullValue())
  596. {
  597. map.put(coerceToType(facesContext, key, keyClass), null);
  598. }
  599. else
  600. {
  601. Object value = entry.getValue();
  602. if (ContainerUtils.isValueReference((String) value))
  603. {
  604. valueExpression = expFactory.createValueExpression(elContext, (String) value, Object.class);
  605. value = valueExpression.getValue(elContext);
  606. }
  607. map.put(coerceToType(facesContext, key, keyClass), coerceToType(facesContext, value, valueClass));
  608. }
  609. }
  610. }
  611. private void initializeList(FacesContext facesContext, ListEntries listEntries, List<? super Object> list)
  612. {
  613. Application application = facesContext.getApplication();
  614. Class<?> valueClass = (listEntries.getValueClass() == null)
  615. ? String.class : ClassUtils.simpleJavaTypeToClass(listEntries.getValueClass());
  616. ExpressionFactory expFactory = application.getExpressionFactory();
  617. ELContext elContext = facesContext.getELContext();
  618. for (Iterator<? extends ListEntry> iterator = listEntries.getListEntries(); iterator.hasNext();)
  619. {
  620. ListEntry entry = iterator.next();
  621. if (entry.isNullValue())
  622. {
  623. list.add(null);
  624. }
  625. else
  626. {
  627. Object value = entry.getValue();
  628. if (ContainerUtils.isValueReference((String) value))
  629. {
  630. ValueExpression valueExpression = expFactory.createValueExpression(elContext, (String) value,
  631. Object.class);
  632. value = valueExpression.getValue(elContext);
  633. }
  634. list.add(coerceToType(facesContext, value, valueClass));
  635. }
  636. }
  637. }
  638. private RuntimeConfig getRuntimeConfig(FacesContext facesContext)
  639. {
  640. if (_runtimeConfig == null)
  641. {
  642. _runtimeConfig = RuntimeConfig.getCurrentInstance(facesContext.getExternalContext());
  643. }
  644. return _runtimeConfig;
  645. }
  646. }