use of org.apache.tapestry5.services.ComponentEventRequestParameters in project tapestry-5 by apache.
the class ComponentEventLinkEncoderImpl method createComponentEventLink.
public Link createComponentEventLink(ComponentEventRequestParameters parameters, boolean forForm) {
StringBuilder builder = new StringBuilder(BUFFER_SIZE);
// Build up the absolute URI.
String activePageName = parameters.getActivePageName();
String containingPageName = parameters.getContainingPageName();
String eventType = parameters.getEventType();
String nestedComponentId = parameters.getNestedComponentId();
boolean hasComponentId = InternalUtils.isNonBlank(nestedComponentId);
builder.append(contextPath);
encodeAppFolderAndLocale(builder);
builder.append(SLASH);
builder.append(activePageName.toLowerCase());
if (hasComponentId) {
builder.append('.');
builder.append(nestedComponentId);
}
if (!hasComponentId || !eventType.equals(EventConstants.ACTION)) {
builder.append(':');
builder.append(encodePageName(eventType));
}
appendContext(true, parameters.getEventContext(), builder);
Link result = new LinkImpl(builder.toString(), forForm, requestSecurityManager.checkPageSecurity(activePageName), response, contextPathEncoder, baseURLSource);
EventContext pageActivationContext = parameters.getPageActivationContext();
if (pageActivationContext.getCount() != 0) {
// Reuse the builder
builder.setLength(0);
appendContext(true, pageActivationContext, builder);
// Omit that first slash
result.addParameter(InternalConstants.PAGE_CONTEXT_NAME, builder.substring(1));
}
if (!containingPageName.equalsIgnoreCase(activePageName))
result.addParameter(InternalConstants.CONTAINER_PAGE_NAME, encodePageName(containingPageName));
return result;
}
use of org.apache.tapestry5.services.ComponentEventRequestParameters in project tapestry-5 by apache.
the class ComponentEventLinkEncoderImpl method decodeComponentEventRequest.
public ComponentEventRequestParameters decodeComponentEventRequest(Request request) {
String explicitLocale = null;
// Split the path around slashes into a mutable list of terms, which will be consumed term by term.
String requestPath = request.getPath();
if (applicationFolderPrefix != null) {
requestPath = removeApplicationPrefix(requestPath);
}
List<String> path = splitPath(requestPath);
if (path.isEmpty()) {
return null;
}
// Next up: the locale (which is optional)
String potentialLocale = path.get(0);
if (localizationSetter.isSupportedLocaleName(potentialLocale)) {
explicitLocale = potentialLocale;
path.remove(0);
}
StringBuilder pageName = new StringBuilder(100);
String sep = "";
while (!path.isEmpty()) {
String name = path.remove(0);
String eventType = EventConstants.ACTION;
String nestedComponentId = "";
boolean found = false;
// First, look for an explicit action name.
int colonx = name.lastIndexOf(':');
if (colonx > 0) {
found = true;
eventType = name.substring(colonx + 1);
name = name.substring(0, colonx);
}
int dotx = name.indexOf('.');
if (dotx > 0) {
found = true;
nestedComponentId = name.substring(dotx + 1);
name = name.substring(0, dotx);
}
pageName.append(sep).append(name);
if (found) {
ComponentEventRequestParameters result = validateAndConstructComponentEventRequest(request, pageName.toString(), nestedComponentId, eventType, path);
if (result == null) {
return result;
}
if (explicitLocale == null) {
setLocaleFromRequest(request);
} else {
localizationSetter.setLocaleFromLocaleName(explicitLocale);
}
return result;
}
// Continue on to the next name in the path
sep = "/";
}
return null;
}
use of org.apache.tapestry5.services.ComponentEventRequestParameters in project tapestry-5 by apache.
the class ComponentEventRequestHandlerImpl method handle.
public void handle(ComponentEventRequestParameters parameters) throws IOException {
Page activePage = cache.get(parameters.getActivePageName());
if (pageActivator.activatePage(activePage.getRootElement().getComponentResources(), parameters.getPageActivationContext(), resultProcessor)) {
return;
}
Page containerPage = cache.get(parameters.getContainingPageName());
TrackableComponentEventCallback callback = new ComponentResultProcessorWrapper(resultProcessor);
environment.push(ComponentEventResultProcessor.class, resultProcessor);
environment.push(TrackableComponentEventCallback.class, callback);
ComponentPageElement element = containerPage.getComponentElementByNestedId(parameters.getNestedComponentId());
boolean handled = element.triggerContextEvent(parameters.getEventType(), parameters.getEventContext(), callback);
if (!handled) {
throw new TapestryException(String.format("Request event '%s' (on component %s) was not handled; you must provide a matching event handler method in the component or in one of its containers.", parameters.getEventType(), element.getCompleteId()), element, null);
}
environment.pop(TrackableComponentEventCallback.class);
environment.pop(ComponentEventResultProcessor.class);
if (callback.isAborted()) {
callback.rethrow();
return;
}
if (!response.isCommitted()) {
resultProcessor.processResultValue(activePage.getName());
}
}
use of org.apache.tapestry5.services.ComponentEventRequestParameters in project tapestry-5 by apache.
the class LinkSourceImplTest method testEventLinkCreation2.
private void testEventLinkCreation2(String pageName, String nestedId, String eventType, boolean forForm, Object... context) {
Page primaryPage = mockPage();
PageRenderQueue queue = mockPageRenderQueue();
PageActivationContextCollector collector = mockPageActivationContextCollector();
LinkCreationListener2 listener = mockLinkCreationListener2();
ComponentEventLinkEncoder linkEncoder = mockComponentEventLinkEncoder();
Link link = mockLink();
ArrayEventContext eventContext = new ArrayEventContext(typeCoercer, context);
ArrayEventContext pageEventContext = new ArrayEventContext(typeCoercer, "a", "b");
train_getRenderingPage(queue, null);
train_getName(primaryPage, pageName);
train_collectPageActivationContext(collector, pageName, "a", "b");
ComponentEventRequestParameters parameters = new ComponentEventRequestParameters(pageName, pageName, nestedId, eventType, pageEventContext, eventContext);
expect(linkEncoder.createComponentEventLink(parameters, forForm)).andReturn(link);
listener.createdComponentEventLink(link, parameters);
List<LinkCreationListener2> configuration = CollectionFactory.newList(listener);
replay();
LinkSource source = new LinkSourceImpl(queue, collector, typeCoercer, null, linkEncoder, null, null, configuration);
Link returnedLink = source.createComponentEventLink(primaryPage, nestedId, eventType, forForm, context);
// Make sure the same link is returned.
assertSame(returnedLink, link);
verify();
}
use of org.apache.tapestry5.services.ComponentEventRequestParameters in project tapestry-5 by apache.
the class AjaxComponentEventRequestHandler method handle.
public void handle(ComponentEventRequestParameters parameters) throws IOException {
Page activePage = cache.get(parameters.getActivePageName());
final Holder<Boolean> resultProcessorInvoked = Holder.create();
resultProcessorInvoked.put(false);
ComponentEventResultProcessor interceptor = new ComponentEventResultProcessor() {
public void processResultValue(Object value) throws IOException {
resultProcessorInvoked.put(true);
resultProcessor.processResultValue(value);
}
};
// If we end up doing a partial render, the page render queue service needs to know the
// page that will be rendered (for logging purposes, if nothing else).
queue.setRenderingPage(activePage);
request.setAttribute(InternalConstants.PAGE_NAME_ATTRIBUTE_NAME, parameters.getActivePageName());
if (pageActivator.activatePage(activePage.getRootElement().getComponentResources(), parameters.getPageActivationContext(), interceptor))
return;
Page containerPage = cache.get(parameters.getContainingPageName());
ComponentPageElement element = containerPage.getComponentElementByNestedId(parameters.getNestedComponentId());
// In many cases, the triggered element is a Form that needs to be able to
// pass its event handler return values to the correct result processor.
// This is certainly the case for forms.
TrackableComponentEventCallback callback = new ComponentResultProcessorWrapper(interceptor);
environment.push(ComponentEventResultProcessor.class, interceptor);
environment.push(TrackableComponentEventCallback.class, callback);
boolean handled = element.triggerContextEvent(parameters.getEventType(), parameters.getEventContext(), callback);
if (!handled)
throw new TapestryException(String.format("Request event '%s' (on component %s) was not handled; you must provide a matching event handler method in the component or in one of its containers.", parameters.getEventType(), element.getCompleteId()), element, null);
environment.pop(TrackableComponentEventCallback.class);
environment.pop(ComponentEventResultProcessor.class);
// If the result processor was passed a value, then it will already have rendered. Otherwise it was not passed a value,
// but it's still possible that we still want to do a partial page render ... if filters were added to the render queue.
// In that event, run the partial page render now and return.
boolean wasInvoked = resultProcessorInvoked.get();
if ((!wasInvoked) && queue.isPartialRenderInitialized()) {
partialRenderer.renderPartialPageMarkup();
return;
}
if (wasInvoked) {
return;
}
// Send an empty JSON reply if no value was returned from the component event handler method.
// This is the typical behavior when an Ajax component event handler returns null. It still
// will go through a pipeline that will add information related to partial page rendering.
resultProcessor.processResultValue(new JSONObject());
}
Aggregations