New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[TOMEE-2060] Make app naming context read only (switched on/off with property) #72
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -81,6 +81,7 @@ | |
import org.apache.openejb.core.SimpleTransactionSynchronizationRegistry; | ||
import org.apache.openejb.core.TransactionSynchronizationRegistryWrapper; | ||
import org.apache.openejb.core.WebContext; | ||
import org.apache.openejb.core.ivm.ContextHandler; | ||
import org.apache.openejb.core.ivm.IntraVmProxy; | ||
import org.apache.openejb.core.ivm.naming.ContextualJndiReference; | ||
import org.apache.openejb.core.ivm.naming.IvmContext; | ||
|
@@ -1029,6 +1030,14 @@ private AppContext createApplication(final AppInfo appInfo, ClassLoader classLoa | |
|
||
systemInstance.fireEvent(new AssemblerAfterApplicationCreated(appInfo, appContext, allDeployments)); | ||
logger.info("createApplication.success", appInfo.path); | ||
|
||
//TODO: set proper default | ||
//required by spec: EE.5.3.4, used together with tomcat#jndiExceptionOnFailedWrite | ||
if("true".equals(SystemInstance.get().getProperty("forceReadOnlyAppNamingContext", "true"))) { | ||
ensureAppNamingContextIsReadOnly(allDeployments); | ||
//TODO message | ||
logger.info("createApplication.success", appInfo.path); | ||
} | ||
|
||
return appContext; | ||
} catch (final ValidationException | DeploymentException ve) { | ||
|
@@ -1049,6 +1058,19 @@ private AppContext createApplication(final AppInfo appInfo, ClassLoader classLoa | |
} | ||
} | ||
|
||
private void ensureAppNamingContextIsReadOnly(final List<BeanContext> allDeployments) { | ||
for(BeanContext beanContext : allDeployments) { | ||
Context ctx = beanContext.getJndiContext(); | ||
if(ctx instanceof IvmContext) { | ||
((IvmContext) ctx).setReadOnly(true); | ||
} else if(ctx instanceof ContextHandler) { | ||
((ContextHandler)ctx).setReadOnly(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. side note on casting: on the list we got a discussion saying we prefer the ${type}.class.cast(instance) style instead of (($type) instance). Not a blocker for me but just mentionning it if you see that style in the code elsewhere. |
||
} else { | ||
//TODO: log only? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. shouldn't be possible so can be ignored for now |
||
} | ||
} | ||
} | ||
|
||
private List<String> getDuplicates(final AppInfo appInfo) { | ||
final List<String> used = new ArrayList<String>(); | ||
for (final EjbJarInfo ejbJarInfo : appInfo.ejbJars) { | ||
|
@@ -2143,6 +2165,9 @@ public void destroyApplication(final AppInfo appInfo) throws UndeployException { | |
continue; | ||
} | ||
|
||
if(globalContext instanceof IvmContext) { | ||
((IvmContext) globalContext).setReadOnly(false); | ||
} | ||
unbind(globalContext, path); | ||
unbind(globalContext, "openejb/global/" + path.substring("java:".length())); | ||
unbind(globalContext, path.substring("java:global".length())); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -87,7 +87,12 @@ public IvmContext(final String nodeName) { | |
} | ||
|
||
public IvmContext(final NameNode node) { | ||
this(node, false); | ||
} | ||
|
||
public IvmContext(final NameNode node, final boolean isReadOnly) { | ||
mynode = node; | ||
readOnly = isReadOnly; | ||
// mynode.setMyContext(this); | ||
} | ||
|
||
|
@@ -147,7 +152,7 @@ If the object has been resolved in the past from this context and the specified | |
Object obj = fastCache.get(compoundName); | ||
if (obj == null) { | ||
try { | ||
obj = mynode.resolve(new ParsedName(compoundName)); | ||
obj = mynode.resolve(new ParsedName(compoundName), readOnly); | ||
} catch (final NameNotFoundException nnfe) { | ||
obj = federate(compositName); | ||
} | ||
|
@@ -293,7 +298,9 @@ public Object lookup(final Name compositName) throws NamingException { | |
} | ||
|
||
public void bind(String name, final Object obj) throws NamingException { | ||
checkReadOnly(); | ||
if(checkReadOnly()) { | ||
return; | ||
} | ||
final int indx = name.indexOf(":"); | ||
if (indx > -1) { | ||
/* | ||
|
@@ -328,7 +335,9 @@ public void rebind(final Name name, final Object obj) throws NamingException { | |
} | ||
|
||
public void unbind(String name) throws NamingException { | ||
checkReadOnly(); | ||
if(checkReadOnly()) { | ||
return; | ||
} | ||
final int indx = name.indexOf(":"); | ||
if (indx > -1) { | ||
/* | ||
|
@@ -399,7 +408,10 @@ public void destroySubcontext(final Name name) throws NamingException { | |
} | ||
|
||
public Context createSubcontext(String name) throws NamingException { | ||
checkReadOnly(); | ||
if(checkReadOnly()) { | ||
//TODO: throw exception or return null? tomcat returns null | ||
return null; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. null is fine if there is a one time - 10 calls will log a single time - log line (warning?) |
||
} | ||
final int indx = name.indexOf(":"); | ||
if (indx > -1) { | ||
/* | ||
|
@@ -411,7 +423,7 @@ public Context createSubcontext(String name) throws NamingException { | |
if (fastCache.containsKey(name)) { | ||
throw new NameAlreadyBoundException(); | ||
} else { | ||
return mynode.createSubcontext(new ParsedName(name)); | ||
return mynode.createSubcontext(new ParsedName(name), readOnly); | ||
} | ||
} | ||
|
||
|
@@ -477,9 +489,36 @@ public String getNameInNamespace() throws NamingException { | |
public void close() throws NamingException { | ||
} | ||
|
||
protected void checkReadOnly() throws OperationNotSupportedException { | ||
//TODO: rename? isReadOnly? | ||
/* | ||
* return false if current naming context is not marked as read only | ||
* return true if current naming context is marked as read only and system property jndiExceptionOnFailedWrite is set to false | ||
* | ||
* throws OperationNotSupportedException if naming context: | ||
* - is marked as read only and | ||
* - system property jndiExceptionOnFailedWrite is set to true | ||
* | ||
* jndiExceptionOnFailedWrite property is defined by tomcat and is used in similar context for web app components | ||
* https://tomcat.apache.org/tomcat-7.0-doc/config/context.html#jndiExceptionOnFailedWrite | ||
* | ||
*/ | ||
protected boolean checkReadOnly() throws OperationNotSupportedException { | ||
//TODO: should it log? | ||
if (readOnly) { | ||
throw new OperationNotSupportedException(); | ||
//alignment with tomcat behavior | ||
if("true".equals(System.getProperty("jndiExceptionOnFailedWrite"))) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. SystemInstance.get().getProperty and openejb prefix as well, default should fail as before |
||
throw new OperationNotSupportedException(); | ||
} | ||
return true; | ||
} | ||
return false; | ||
} | ||
|
||
public void setReadOnly(boolean isReadOnly) { | ||
//TODO: should it log? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no need to log it until there is an issue with this being called (which is more in write methods) |
||
this.readOnly = isReadOnly; | ||
if(mynode != null) { | ||
mynode.setReadOnly(readOnly); | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please prefix it openejb. (openejb.forceReadOnlyAppNamingContext)
also shouldnt the default be false to ensure it is writable by default (backward compatibility)
also think createApplication.success is not the right key yet ;)