You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by we...@apache.org on 2009/12/16 22:16:02 UTC
svn commit: r891428 -
/myfaces/extensions/scripting/trunk/core/core/src/main/java/org/apache/myfaces/scripting/api/BaseWeaver.java
Author: werpu
Date: Wed Dec 16 21:16:00 2009
New Revision: 891428
URL: http://svn.apache.org/viewvc?rev=891428&view=rev
Log:
added mutexes on the correct parts of the system so that the iteration over the beans does not happen at the same time as the alteration
Modified:
myfaces/extensions/scripting/trunk/core/core/src/main/java/org/apache/myfaces/scripting/api/BaseWeaver.java
Modified: myfaces/extensions/scripting/trunk/core/core/src/main/java/org/apache/myfaces/scripting/api/BaseWeaver.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/scripting/trunk/core/core/src/main/java/org/apache/myfaces/scripting/api/BaseWeaver.java?rev=891428&r1=891427&r2=891428&view=diff
==============================================================================
--- myfaces/extensions/scripting/trunk/core/core/src/main/java/org/apache/myfaces/scripting/api/BaseWeaver.java (original)
+++ myfaces/extensions/scripting/trunk/core/core/src/main/java/org/apache/myfaces/scripting/api/BaseWeaver.java Wed Dec 16 21:16:00 2009
@@ -19,6 +19,22 @@
* @author Werner Punz
* <p/>
* Refactored the common weaver code into a base class
+ * <p/>
+ * <p/>
+ * note we added a bean dropping code, the bean dropping works that way
+ * if we are the first request after a compile issued
+ * we drop all beans
+ * <p/>
+ * every other request has to drop only the session
+ * and custom scoped beans
+ * <p/>
+ * we set small mutexes to avoid at least in our code synchronisation issues
+ * the mutexes are as atomic as possible to avoid speed problems.
+ * <p/>
+ * Unfortunately if someone alters the beanmap from outside while we reload
+ * we for now cannot do anything until we have covered that in the myfaces core!
+ * <p/>
+ * Since all weavers are applicatin scoped we can handle the mutexes properly
*/
public abstract class BaseWeaver implements ScriptingWeaver {
@@ -35,6 +51,7 @@
private static final String SCOPE_APPLICATION = "application";
private static final String SCOPE_REQUEST = "request";
+ private static Boolean BEAN_LOCK = new Boolean(true);
public BaseWeaver() {
_reloadingStrategy = new GlobalReloadingStrategy(this);
@@ -262,22 +279,25 @@
return;//no npe allowed
}
Set<String> tainted = new HashSet<String>();
- synchronized (this) {
- for (Map.Entry<String, ReloadingMetadata> it : WeavingContext.getFileChangedDaemon().getClassMap().entrySet()) {
- if (it.getValue().getScriptingEngine() == getScriptingEngine() && it.getValue().isTainted()) {
- tainted.add(it.getKey());
- }
+ for (Map.Entry<String, ReloadingMetadata> it : WeavingContext.getFileChangedDaemon().getClassMap().entrySet()) {
+ if (it.getValue().getScriptingEngine() == getScriptingEngine() && it.getValue().isTainted()) {
+ tainted.add(it.getKey());
}
}
if (tainted.size() > 0) {
boolean managedBeanTainted = false;
//We now have to check if the tainted classes belong to the managed beans
Set<String> managedBeanClasses = new HashSet<String>();
- synchronized (this) {
- Map<String, ManagedBean> mbeans = RuntimeConfig.getCurrentInstance(FacesContext.getCurrentInstance().getExternalContext()).getManagedBeans();
- for (Map.Entry<String, ManagedBean> entry : mbeans.entrySet()) {
- managedBeanClasses.add(entry.getValue().getManagedBeanClassName());
- }
+
+ Map<String, ManagedBean> mbeans = RuntimeConfig.getCurrentInstance(FacesContext.getCurrentInstance().getExternalContext()).getManagedBeans();
+ Map<String, ManagedBean> workCopy = null;
+
+ synchronized (BEAN_LOCK) {
+ workCopy = makeSnapshot(mbeans);
+ }
+
+ for (Map.Entry<String, ManagedBean> entry : workCopy.entrySet()) {
+ managedBeanClasses.add(entry.getValue().getManagedBeanClassName());
}
for (String taintedClass : tainted) {
if (managedBeanClasses.contains(taintedClass)) {
@@ -291,25 +311,22 @@
getLog().info("[EXT-SCRIPTING] Tainting all beans to avoid classcast exceptions");
if (managedBeanTainted) {
- synchronized (this) {
- Map<String, ManagedBean> workCopy = makeSnapshot(mbeans);
-
- for (Map.Entry<String, ManagedBean> entry : workCopy.entrySet()) {
- Class managedBeanClass = entry.getValue().getManagedBeanClass();
- if (WeavingContext.isDynamic(managedBeanClass)) {
- //managed bean class found we drop the class from our session
+ for (Map.Entry<String, ManagedBean> entry : workCopy.entrySet()) {
+ Class managedBeanClass = entry.getValue().getManagedBeanClass();
+ if (WeavingContext.isDynamic(managedBeanClass)) {
+ //managed bean class found we drop the class from our session
+ synchronized (BEAN_LOCK) {
removeBeanReferences(entry.getValue());
}
- //one bean tainted we have to taint all dynamic beans otherwise we will get classcast
- //exceptions
- getLog().info("[EXT-SCRIPTING] Tainting ");
- ReloadingMetadata metaData = WeavingContext.getFileChangedDaemon().getClassMap().get(managedBeanClass.getName());
- if (metaData != null) {
- metaData.setTainted(true);
- }
+ }
+ //one bean tainted we have to taint all dynamic beans otherwise we will get classcast
+ //exceptions
+ getLog().info("[EXT-SCRIPTING] Tainting ");
+ ReloadingMetadata metaData = WeavingContext.getFileChangedDaemon().getClassMap().get(managedBeanClass.getName());
+ if (metaData != null) {
+ metaData.setTainted(true);
}
}
-
}
}
@@ -325,10 +342,13 @@
* @return
*/
private Map<String, ManagedBean> makeSnapshot(Map<String, ManagedBean> mbeans) {
- Map<String, ManagedBean> workCopy = new HashMap<String, ManagedBean>(mbeans.size());
+ Map<String, ManagedBean> workCopy = null;
+
+ workCopy = new HashMap<String, ManagedBean>(mbeans.size());
for (Map.Entry<String, ManagedBean> entry : mbeans.entrySet()) {
workCopy.put(entry.getKey(), entry.getValue());
}
+
return workCopy;
}
@@ -352,37 +372,41 @@
*/
private void refreshPersonalScopedBeans() {
- synchronized (this) {
- Map<String, ManagedBean> mbeans = RuntimeConfig.getCurrentInstance(FacesContext.getCurrentInstance().getExternalContext()).getManagedBeans();
- //the map is immutable but in between scanning might change it so we make a full copy of the map
+ Map<String, ManagedBean> mbeans = RuntimeConfig.getCurrentInstance(FacesContext.getCurrentInstance().getExternalContext()).getManagedBeans();
+ //the map is immutable but in between scanning might change it so we make a full copy of the map
- //We can synchronized the refresh, but if someone alters
- //the bean map from outside we still get race conditions
- //But for most cases this mutex should be enough
- Map<String, ManagedBean> workCopy = makeSnapshot(mbeans);
+ //We can synchronized the refresh, but if someone alters
+ //the bean map from outside we still get race conditions
+ //But for most cases this mutex should be enough
- for (Map.Entry<String, ManagedBean> entry : workCopy.entrySet()) {
+ Map<String, ManagedBean> workCopy = null;
+ synchronized (BEAN_LOCK) {
+ workCopy = makeSnapshot(mbeans);
+ }
- Class managedBeanClass = entry.getValue().getManagedBeanClass();
- if (WeavingContext.isDynamic(managedBeanClass)) {
- String scope = entry.getValue().getManagedBeanScope();
-
- if (scope != null && !scope.equalsIgnoreCase(SCOPE_APPLICATION)) {
- if (scope.equalsIgnoreCase(SCOPE_REQUEST)) {
- //request, nothing has to be done here
- return;
- }
+ for (Map.Entry<String, ManagedBean> entry : workCopy.entrySet()) {
+
+ Class managedBeanClass = entry.getValue().getManagedBeanClass();
+ if (WeavingContext.isDynamic(managedBeanClass)) {
+ String scope = entry.getValue().getManagedBeanScope();
+
+ if (scope != null && !scope.equalsIgnoreCase(SCOPE_APPLICATION)) {
+ if (scope.equalsIgnoreCase(SCOPE_REQUEST)) {
+ //request, nothing has to be done here
+ return;
+ }
+ synchronized (BEAN_LOCK) {
if (scope.equalsIgnoreCase(SCOPE_SESSION)) {
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove(entry.getValue().getManagedBeanName());
} else {
removeCustomScopedBean(entry.getValue());
}
}
-
}
- updateBeanRefreshTime();
}
+
+ updateBeanRefreshTime();
}
}