Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.xpn.xwiki.internal;

import static com.celements.execution.XWikiExecutionProp.*;
import static org.junit.Assert.*;

import org.junit.Test;
import org.xwiki.context.Execution;
import org.xwiki.context.ExecutionContext;
import org.xwiki.context.ExecutionContextInitializer;
import org.xwiki.model.reference.DocumentReference;
import org.xwiki.model.reference.WikiReference;

import com.xpn.xwiki.doc.XWikiDocument;
import com.celements.common.test.AbstractComponentTest;
import com.xpn.xwiki.user.api.XWikiUser;

public class XWikiExecutionContextInitializerTest extends AbstractComponentTest {

@Test
public void test_initializeFromSource() throws Exception {
assertTrue(getBeanFactory().getBeansOfType(ExecutionContextInitializer.class).values().stream()
.anyMatch(XWikiExecutionContextInitializer.class::isInstance));
ExecutionContext source = getBeanFactory().getBean(Execution.class).getContext();
XWikiDocument doc = new XWikiDocument(new DocumentReference("wiki", "Space", "Doc"));
XWikiUser user = new XWikiUser("XWiki.User");
source.set(WIKI, new WikiReference("wiki"));
source.set(DOC, doc);
source.set(XWIKI_USER, user);

ExecutionContext target = new ExecutionContext();
getBeanFactory().getBean(XWikiExecutionContextInitializer.class).initialize(target, source);

assertEquals(new WikiReference("wiki"), target.get(WIKI).orElseThrow());
assertSame(doc, target.get(DOC).orElseThrow());
assertSame(user, target.get(XWIKI_USER).orElseThrow());
assertNotSame(getXContext(), target.get(XWIKI_CONTEXT).orElseThrow());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package org.xwiki.context.internal;

import static com.celements.execution.XWikiExecutionProp.*;
import static org.junit.Assert.*;

import org.junit.Before;
import org.junit.Test;
import org.xwiki.context.Execution;
import org.xwiki.context.ExecutionContext;

import com.celements.common.test.AbstractComponentTest;

public final class DefaultExecutionContextManagerTest extends AbstractComponentTest {

private DefaultExecutionContextManager contextManager;
private Execution execution;

@Before
public void prepareTest() throws Exception {
contextManager = getBeanFactory().getBean(DefaultExecutionContextManager.class);
execution = getBeanFactory().getBean(Execution.class);
}

@Test
public void test_cloneContext() throws Exception {
ExecutionContext context = execution.getContext();
ExecutionContext clonedContext = contextManager.clone(context);

assertNotSame(context, clonedContext);
assertTrue(clonedContext.get(XWIKI_CONTEXT).isPresent());
assertSame(context, execution.getContext());
}

@Test
public void test_cloneWithoutCurrentContext() throws Exception {
ExecutionContext originalContext = execution.getContext();
ExecutionContext context = new ExecutionContext();
execution.removeContext();
try {
ExecutionContext clonedContext = contextManager.clone(context);

assertNotNull(clonedContext);
assertTrue(clonedContext.get(XWIKI_CONTEXT).isPresent());
assertNull(execution.getContext());
} finally {
execution.setContext(originalContext);
}
}

}
1 change: 0 additions & 1 deletion celements-servlet/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@
<artifactId>xwiki-core-shared-tests</artifactId>
<scope>test</scope>
</dependency>

</dependencies>
<scm>
<connection>scm:git:git@github.com:celements/celements-base.git</connection>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,12 @@
*/
package org.xwiki.context;

import org.xwiki.component.annotation.ComponentRole;

/**
* Allows setting/retrieving the {@link ExecutionContext}.
*
* @version $Id$
* @since 1.5M2
*/
@ComponentRole
public interface Execution {

ExecutionContext getContext();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@
*/
package org.xwiki.context;

import org.xwiki.component.annotation.ComponentRole;
import javax.annotation.Nullable;
import javax.validation.constraints.NotNull;

@ComponentRole
public interface ExecutionContextInitializer {

void initialize(ExecutionContext context) throws ExecutionContextException;
void initialize(@NotNull ExecutionContext context, @Nullable ExecutionContext source)
throws ExecutionContextException;

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,29 @@
*/
package org.xwiki.context;

import org.xwiki.component.annotation.ComponentRole;
import javax.validation.constraints.NotNull;

@ComponentRole
public interface ExecutionContextManager {

void initialize(ExecutionContext context) throws ExecutionContextException;
/**
* Initializes the given context by asking all registered {@link ExecutionContextInitializer}s to
* initialize their module-specific state.
*
* @param context
* the context to initialize
*/
void initialize(@NotNull ExecutionContext context) throws ExecutionContextException;

/**
* Perform deep cloning of Execution Context properties by calling all implementations of
* {@link ExecutionContextCloner}.
* Creates and initializes an independent child context by asking all registered
* {@link ExecutionContextInitializer}s to initialize their module-specific state from the source
* context.
*
* @return the cloned Execution Context
* @param context
* the context from which state is inherited
* @return the cloned and initialized context
*/
ExecutionContext clone(ExecutionContext context) throws ExecutionContextException;
@NotNull
ExecutionContext clone(@NotNull ExecutionContext context) throws ExecutionContextException;

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@
*/
package org.xwiki.context.internal;

import static com.google.common.base.Preconditions.*;

import java.util.Stack;

import org.xwiki.component.annotation.Component;
import org.springframework.stereotype.Component;
import org.xwiki.context.Execution;
import org.xwiki.context.ExecutionContext;

Expand All @@ -41,27 +43,37 @@ public class DefaultExecution implements Execution {

private final ThreadLocal<Stack<ExecutionContext>> context = new ThreadLocal<>();

private Stack<ExecutionContext> getOrCreateStack() {
Stack<ExecutionContext> stack = context.get();
if (stack == null) {
stack = new Stack<>();
context.set(stack);
}
return stack;
}

@Override
public void pushContext(ExecutionContext context) {
this.context.get().push(context);
public void pushContext(ExecutionContext newContext) {
getOrCreateStack().push(checkNotNull(newContext));
}

@Override
public void popContext() {
context.get().pop();
Stack<ExecutionContext> stack = context.get();
checkState((stack != null) && !stack.isEmpty(), "no execution context to pop");
stack.pop();
}

@Override
public ExecutionContext getContext() {
Stack<ExecutionContext> stack = context.get();
return stack == null ? null : stack.peek();
return (stack == null) || stack.isEmpty() ? null : stack.peek();
}

@Override
public void setContext(ExecutionContext context) {
Stack<ExecutionContext> stack = new Stack<>();
stack.push(context);
this.context.set(stack);
public void setContext(ExecutionContext newContext) {
removeContext();
pushContext(newContext);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@
*/
package org.xwiki.context.internal;

import java.util.ArrayList;
import java.util.List;

import org.xwiki.component.annotation.Component;
import org.xwiki.component.annotation.Requirement;
import javax.inject.Inject;

import org.springframework.stereotype.Component;
import org.xwiki.context.Execution;
import org.xwiki.context.ExecutionContext;
import org.xwiki.context.ExecutionContextException;
import org.xwiki.context.ExecutionContextInitializer;
Expand All @@ -33,48 +34,39 @@
@Component
public class DefaultExecutionContextManager implements ExecutionContextManager {

@Requirement
private List<ExecutionContextInitializer> initializers = new ArrayList<>();
private final List<ExecutionContextInitializer> initializers;
private final Execution execution;

@Inject
public DefaultExecutionContextManager(
List<ExecutionContextInitializer> initializers,
Execution execution) {
this.initializers = List.copyOf(initializers);
this.execution = execution;
}

@Override
public ExecutionContext clone(ExecutionContext context) throws ExecutionContextException {
// Ideally we would like to do a deep cloning here. However it's just too hard since we don't
// control objects put in the Execution Context and they can be of any type, including Maps
// which are cloneable but only do shallow clones.
// Thus instead we recreate the Execution Context from scratch and reinitialize it by calling
// all the Execution Context Initializers on it.
ExecutionContext clonedContext = new ExecutionContext();
clonedContext.setProperty("xwikicontext", context.getProperty("xwikicontext"));
initialize(clonedContext);
// Manually clone the Velocity Context too since currently the XWikiVelocityContextInitializer
// is not yet implemented.
// Note that we're using reflection since we don't want to add a dependency on Velocity module
// since that would cause a cyclic dependency.
// TODO: Fix this when XWikiVelocityContextInitializer is implemented
// Note that Velocity doesn't provide a method for cloning a Velocity Context
// (see https://issues.apache.org/jira/browse/VELOCITY-712). Thus we're not cloning the Velocity
// Context which can raise problems if the included page modifies the Velocity Context...
Object velocityContext = context.getProperty("velocityContext");
if (velocityContext != null) {
try {
clonedContext.setProperty("velocityContext",
velocityContext.getClass().getMethod("clone").invoke(velocityContext));
} catch (Exception e) {
throw new ExecutionContextException(
"Failed to clone Velocity Context for the new Execution Context", e);
}
var clone = new ExecutionContext();
execution.pushContext(clone);
try {
initialize(clone, context);
} finally {
execution.popContext();
}
return clonedContext;
return clone;
}

@Override
public void initialize(ExecutionContext context) throws ExecutionContextException {
initialize(context, null);
}

private void initialize(ExecutionContext context, ExecutionContext source)
throws ExecutionContextException {
for (ExecutionContextInitializer initializer : this.initializers) {
initializer.initialize(context);
initializer.initialize(context, source);
}
}

public void addExecutionContextInitializer(ExecutionContextInitializer initializer) {
this.initializers.add(initializer);
}
}
2 changes: 0 additions & 2 deletions celements-servlet/src/main/resources/META-INF/components.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
org.xwiki.context.internal.DefaultExecution
org.xwiki.context.internal.DefaultExecutionContextManager
org.xwiki.container.internal.DefaultContainer
org.xwiki.container.internal.DefaultRequestInitializerManager
org.xwiki.container.internal.DefaultApplicationContextListenerManager
Expand Down

This file was deleted.

Loading