Author: remy.maucherat(a)jboss.com
Date: 2010-01-04 11:32:17 -0500 (Mon, 04 Jan 2010)
New Revision: 1351
Modified:
trunk/java/org/apache/catalina/session/PersistentManagerBase.java
trunk/java/org/apache/catalina/session/StoreBase.java
trunk/java/org/apache/jasper/compiler/Generator.java
trunk/java/org/apache/jasper/compiler/JspUtil.java
trunk/java/org/apache/jasper/compiler/Validator.java
trunk/java/org/apache/jasper/resources/LocalStrings.properties
Log:
- Port Tomcat patches.
- All minor, with the exception of some EL fixes.
Modified: trunk/java/org/apache/catalina/session/PersistentManagerBase.java
===================================================================
--- trunk/java/org/apache/catalina/session/PersistentManagerBase.java 2009-12-17 17:45:16
UTC (rev 1350)
+++ trunk/java/org/apache/catalina/session/PersistentManagerBase.java 2010-01-04 16:32:17
UTC (rev 1351)
@@ -24,6 +24,9 @@
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
+import java.util.HashMap;
+import java.util.Map;
+
import org.apache.catalina.Container;
import org.apache.catalina.Context;
import org.apache.catalina.Lifecycle;
@@ -205,6 +208,13 @@
protected long processingTime = 0;
+ /**
+ * Sessions currently being swapped in and the associated locks
+ */
+ private final Map<String,Object> sessionSwapInLocks =
+ new HashMap<String,Object>();
+
+
// ------------------------------------------------------------- Properties
@@ -382,7 +392,7 @@
/**
- * Set the maximum number of actives Sessions allowed, or -1 for
+ * Set the maximum number of active Sessions allowed, or -1 for
* no limit.
*
* @param max The new maximum number of sessions
@@ -771,54 +781,89 @@
if (store == null)
return null;
+ Object swapInLock = null;
+
+ /*
+ * The purpose of this sync and these locks is to make sure that a
+ * session is only loaded once. It doesn't matter if the lock is removed
+ * and then another thread enters this method and tries to load the same
+ * session. That thread will re-create a swapIn lock for that session,
+ * quickly find that the session is already in sessions, use it and
+ * carry on.
+ */
+ synchronized (this) {
+ swapInLock = sessionSwapInLocks.get(id);
+ if (swapInLock == null) {
+ swapInLock = new Object();
+ sessionSwapInLocks.put(id, swapInLock);
+ }
+ }
+
Session session = null;
- try {
- if (SecurityUtil.isPackageProtectionEnabled()){
- try{
- session = (Session)
- AccessController.doPrivileged(new PrivilegedStoreLoad(id));
- }catch(PrivilegedActionException ex){
- Exception exception = ex.getException();
- log.error("Exception in the Store during swapIn: "
- + exception);
- if (exception instanceof IOException){
- throw (IOException)exception;
- } else if (exception instanceof ClassNotFoundException) {
- throw (ClassNotFoundException)exception;
+
+ synchronized (swapInLock) {
+ // First check to see if another thread has loaded the session into
+ // the manager
+ session = sessions.get(id);
+
+ if (session == null) {
+ try {
+ if (SecurityUtil.isPackageProtectionEnabled()){
+ try {
+ session = (Session) AccessController.doPrivileged(
+ new PrivilegedStoreLoad(id));
+ } catch (PrivilegedActionException ex) {
+ Exception e = ex.getException();
+ log.error(sm.getString(
+ "persistentManager.swapInException", id),
+ e);
+ if (e instanceof IOException){
+ throw (IOException)e;
+ } else if (e instanceof ClassNotFoundException) {
+ throw (ClassNotFoundException)e;
+ }
+ }
+ } else {
+ session = store.load(id);
}
+ } catch (ClassNotFoundException e) {
+ String msg = sm.getString(
+ "persistentManager.deserializeError", id);
+ log.error(msg, e);
+ throw new IllegalStateException(msg, e);
}
- } else {
- session = store.load(id);
- }
- } catch (ClassNotFoundException e) {
- log.error(sm.getString("persistentManager.deserializeError", id,
e));
- throw new IllegalStateException
- (sm.getString("persistentManager.deserializeError", id, e));
- }
- if (session == null)
- return (null);
+ if (session != null && !session.isValid()) {
+ log.error(sm.getString(
+ "persistentManager.swapInInvalid", id));
+ session.expire();
+ removeSession(id);
+ session = null;
+ }
- if (!session.isValid()) {
- log.error("session swapped in is invalid or expired");
- session.expire();
- removeSession(id);
- return (null);
+ if (session != null) {
+ if(log.isDebugEnabled())
+ log.debug(sm.getString("persistentManager.swapIn",
id));
+
+ session.setManager(this);
+ // make sure the listeners know about it.
+ ((StandardSession)session).tellNew();
+ add(session);
+ ((StandardSession)session).activate();
+ // endAccess() to ensure timeouts happen correctly.
+ // access() to keep access count correct or it will end up
+ // negative
+ session.access();
+ session.endAccess();
+ }
+ }
}
- if(log.isDebugEnabled())
- log.debug(sm.getString("persistentManager.swapIn", id));
+ // Make sure the lock is removed
+ synchronized (this) {
+ sessionSwapInLocks.remove(id);
+ }
- session.setManager(this);
- // make sure the listeners know about it.
- ((StandardSession)session).tellNew();
- add(session);
- ((StandardSession)session).activate();
- // endAccess() to ensure timeouts happen correctly.
- // access() to keep access count correct or it will end up negative
- session.access();
- session.endAccess();
-
return (session);
}
Modified: trunk/java/org/apache/catalina/session/StoreBase.java
===================================================================
--- trunk/java/org/apache/catalina/session/StoreBase.java 2009-12-17 17:45:16 UTC (rev
1350)
+++ trunk/java/org/apache/catalina/session/StoreBase.java 2010-01-04 16:32:17 UTC (rev
1351)
@@ -173,7 +173,6 @@
*
*/
public void processExpires() {
- long timeNow = System.currentTimeMillis();
String[] keys = null;
if(!started) {
@@ -190,13 +189,16 @@
manager.getContainer().getLogger().debug(getStoreName()+ ":
processExpires check number of " + keys.length + " sessions" );
}
+ long timeNow = System.currentTimeMillis();
+
for (int i = 0; i < keys.length; i++) {
try {
StandardSession session = (StandardSession) load(keys[i]);
if (session == null) {
continue;
}
- if (session.isValid()) {
+ int timeIdle = (int) ((timeNow - session.getThisAccessedTime()) /
1000L);
+ if (timeIdle < session.getMaxInactiveInterval()) {
continue;
}
if (manager.getContainer().getLogger().isDebugEnabled()) {
@@ -209,7 +211,7 @@
// expire swapped out session
session.expire();
}
- remove(session.getIdInternal());
+ remove(keys[i]);
} catch (Exception e) {
manager.getContainer().getLogger().error("Session:
"+keys[i]+"; ", e);
try {
Modified: trunk/java/org/apache/jasper/compiler/Generator.java
===================================================================
--- trunk/java/org/apache/jasper/compiler/Generator.java 2009-12-17 17:45:16 UTC (rev
1350)
+++ trunk/java/org/apache/jasper/compiler/Generator.java 2010-01-04 16:32:17 UTC (rev
1351)
@@ -901,6 +901,54 @@
}
output.append(quote(tx.substring(mark, i)));
}
+ if (expectedType != type && !expectedType.isAssignableFrom(type)) {
+ // Composite expression was evaluated to String
+ // We must coerce it to the expected type.
+ String className = JspUtil.getCanonicalName(expectedType);
+ String methodName = null;
+ if (expectedType.isPrimitive()) {
+ if (expectedType == Boolean.TYPE) {
+ className = "Boolean";
+ methodName = ".booleanValue()";
+ }
+ else if (expectedType == Character.TYPE) {
+ className = "Character";
+ methodName = ".charValue()";
+ }
+ else if (expectedType == Byte.TYPE) {
+ className = "Byte";
+ methodName = ".byteValue()";
+ }
+ else if (expectedType == Short.TYPE) {
+ className = "Short";
+ methodName = ".shortValue()";
+ }
+ else if (expectedType == Integer.TYPE) {
+ className = "Integer";
+ methodName = ".intValue()";
+ }
+ else if (expectedType == Long.TYPE) {
+ className = "Long";
+ methodName = ".longValue()";
+ }
+ else if (expectedType == Float.TYPE) {
+ className = "Float";
+ methodName = ".floatValue()";
+ }
+ else if (expectedType == Double.TYPE) {
+ className = "Double";
+ methodName = ".doubleValue()";
+ }
+ }
+ output.insert(0, "(("
+ + className
+ + ")org.apache.el.lang.ELSupport.coerceToType(");
+
output.append(",").append(className).append(".class))");
+ if (methodName != null) {
+ output.insert(0, '(');
+ output.append(methodName).append(')');
+ }
+ }
return output.toString();
}
@@ -1298,12 +1346,13 @@
}
}
+ // JSP.5.1, Sematics, para 1 - lock not required for request or
+ // page scope
String scopename = "PageContext.PAGE_SCOPE"; // Default to page
- String lock = "_jspx_page_context";
+ String lock = null;
if ("request".equals(scope)) {
scopename = "PageContext.REQUEST_SCOPE";
- lock = "request";
} else if ("session".equals(scope)) {
scopename = "PageContext.SESSION_SCOPE";
lock = "session";
@@ -1320,11 +1369,13 @@
out.print(name);
out.println(" = null;");
- // Lock while getting or creating bean
- out.printin("synchronized (");
- out.print(lock);
- out.println(") {");
- out.pushIndent();
+ // Lock (if required) while getting or creating bean
+ if (lock != null) {
+ out.printin("synchronized (");
+ out.print(lock);
+ out.println(") {");
+ out.pushIndent();
+ }
// Locate bean from context
out.printin(name);
@@ -1427,8 +1478,10 @@
out.printil("}");
// End of lock block
- out.popIndent();
- out.printil("}");
+ if (lock != null) {
+ out.popIndent();
+ out.printil("}");
+ }
n.setEndJavaLine(out.getJavaLine());
}
Modified: trunk/java/org/apache/jasper/compiler/JspUtil.java
===================================================================
--- trunk/java/org/apache/jasper/compiler/JspUtil.java 2009-12-17 17:45:16 UTC (rev 1350)
+++ trunk/java/org/apache/jasper/compiler/JspUtil.java 2010-01-04 16:32:17 UTC (rev 1351)
@@ -463,6 +463,8 @@
c = float.class;
else if ("double".equals(type))
c = double.class;
+ else if ("void".equals(type))
+ c = void.class;
else if (type.indexOf('[') < 0)
c = loader.loadClass(type);
Modified: trunk/java/org/apache/jasper/compiler/Validator.java
===================================================================
--- trunk/java/org/apache/jasper/compiler/Validator.java 2009-12-17 17:45:16 UTC (rev
1350)
+++ trunk/java/org/apache/jasper/compiler/Validator.java 2010-01-04 16:32:17 UTC (rev
1351)
@@ -1128,6 +1128,14 @@
expectedType = "java.lang.Object";
}
}
+ if ("void".equals(expectedType)) {
+ // Can't specify a literal for a
+ // deferred method with an expected type
+ // of void - JSP.2.3.4
+ err.jspError(n,
+ "jsp.error.literal_with_void",
+ tldAttrs[j].getName());
+ }
if (tldAttrs[j].isDeferredValue()) {
// The String litteral must be castable to what is
declared as type
// for the attribute
Modified: trunk/java/org/apache/jasper/resources/LocalStrings.properties
===================================================================
--- trunk/java/org/apache/jasper/resources/LocalStrings.properties 2009-12-17 17:45:16 UTC
(rev 1350)
+++ trunk/java/org/apache/jasper/resources/LocalStrings.properties 2010-01-04 16:32:17 UTC
(rev 1351)
@@ -338,6 +338,7 @@
jsp.error.var_and_varReader=Only one of \'var\' or \'varReader\' may be
specified
jsp.error.missing_var_or_varReader=Missing \'var\' or \'varReader\'
attribute
jsp.warning.bad.urlpattern.propertygroup=Bad value {0} in the url-pattern subelement in
web.xml
+jsp.error.literal_with_void=A literal value was specified for attribute {0} that is
defined as a deferred method with a return type of void. JSP.2.3.4 does not permit literal
values in this case
jsp.error.unknown_attribute_type=Unknown attribute type ({1}) for attribute {0}.
jsp.error.coerce_to_type=Cannot coerce value ({2}) to type ({1}) for attribute {0}.
jsp.error.jspelement.missing.name=Mandatory XML-style \'name\' attribute missing