Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.tcdng.unify.web.ui.AbstractUIController Maven / Gradle / Ivy
/*
* Copyright 2018-2023 The Code Department.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.tcdng.unify.web.ui;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.tcdng.unify.core.UnifyCoreErrorConstants;
import com.tcdng.unify.core.UnifyCoreRequestAttributeConstants;
import com.tcdng.unify.core.UnifyException;
import com.tcdng.unify.core.UnifyOperationException;
import com.tcdng.unify.core.annotation.Configurable;
import com.tcdng.unify.core.constant.LocaleType;
import com.tcdng.unify.core.constant.MimeType;
import com.tcdng.unify.core.util.DataUtils;
import com.tcdng.unify.core.util.StringUtils;
import com.tcdng.unify.core.util.SystemUtils;
import com.tcdng.unify.web.AbstractController;
import com.tcdng.unify.web.ClientRequest;
import com.tcdng.unify.web.ClientResponse;
import com.tcdng.unify.web.ControllerPathParts;
import com.tcdng.unify.web.PathInfoRepository;
import com.tcdng.unify.web.UnifyWebErrorConstants;
import com.tcdng.unify.web.constant.ReadOnly;
import com.tcdng.unify.web.constant.RequestParameterConstants;
import com.tcdng.unify.web.constant.ResetOnWrite;
import com.tcdng.unify.web.constant.ResultMappingConstants;
import com.tcdng.unify.web.constant.Secured;
import com.tcdng.unify.web.constant.SystemInfoConstants;
import com.tcdng.unify.web.ui.constant.PageRequestParameterConstants;
import com.tcdng.unify.web.ui.util.DataTransferUtils;
import com.tcdng.unify.web.ui.widget.Document;
import com.tcdng.unify.web.ui.widget.Page;
import com.tcdng.unify.web.ui.widget.PageManager;
import com.tcdng.unify.web.ui.widget.ResponseWriter;
import com.tcdng.unify.web.ui.widget.ResponseWriterPool;
/**
* Convenient base class for user interface controllers.
*
* @author The Code Department
* @since 1.0
*/
public abstract class AbstractUIController extends AbstractController implements UIController {
private static final Set skipOnPopulateSet = Collections
.unmodifiableSet(new HashSet(Arrays.asList(PageRequestParameterConstants.DOCUMENT,
PageRequestParameterConstants.TARGET_VALUE, PageRequestParameterConstants.WINDOW_NAME,
PageRequestParameterConstants.VALIDATION_ACTION, PageRequestParameterConstants.CONFIRM_MSG,
PageRequestParameterConstants.CONFIRM_MSGICON, PageRequestParameterConstants.CONFIRM_PARAM,
RequestParameterConstants.REMOTE_VIEWER, RequestParameterConstants.REMOTE_ROLECD,
RequestParameterConstants.REMOTE_SESSION_ID, RequestParameterConstants.REMOTE_USERLOGINID,
RequestParameterConstants.REMOTE_USERNAME, RequestParameterConstants.REMOTE_BRANCH_CODE,
RequestParameterConstants.REMOTE_ZONE_CODE, RequestParameterConstants.REMOTE_GLOBAL_ACCESS,
RequestParameterConstants.REMOTE_COLOR_SCHEME, RequestParameterConstants.REMOTE_TENANT_CODE)));
@Configurable
private UIControllerUtil uiControllerUtil;
@Configurable
private PageRequestContextUtil pageRequestContextUtil;
@Configurable
private PageManager pageManager;
@Configurable
private PathInfoRepository pathInfoRepository;
@Configurable
private ResponseWriterPool responseWriterPool;
private boolean readOnly;
private boolean resetOnWrite;
public AbstractUIController(Secured secured, ReadOnly readOnly, ResetOnWrite resetOnWrite) {
super(secured);
this.readOnly = readOnly.isTrue();
this.resetOnWrite = resetOnWrite.isTrue();
}
public void setUiControllerUtil(UIControllerUtil uiControllerUtil) {
this.uiControllerUtil = uiControllerUtil;
}
public void setPageRequestContextUtil(PageRequestContextUtil pageRequestContextUtil) {
this.pageRequestContextUtil = pageRequestContextUtil;
}
public void setPageManager(PageManager pageManager) {
this.pageManager = pageManager;
}
public void setPathInfoRepository(PathInfoRepository pathInfoRepository) {
this.pathInfoRepository = pathInfoRepository;
}
public void setResponseWriterPool(ResponseWriterPool responseWriterPool) {
this.responseWriterPool = responseWriterPool;
}
@Override
public final void process(ClientRequest request, ClientResponse response) throws UnifyException {
try {
final ControllerPathParts reqPathParts = request.getRequestPathParts().getControllerPathParts();
PageController docPageController = null;
ControllerPathParts docPathParts = null;
String documentPath = (String) request.getParameter(PageRequestParameterConstants.DOCUMENT);
if (documentPath != null) {
docPathParts = pathInfoRepository.getControllerPathParts(documentPath);
docPageController = (PageController) getControllerFinder().findController(docPathParts);
pageRequestContextUtil.setRequestDocument((Document) uiControllerUtil.loadRequestPage(docPathParts));
}
pageRequestContextUtil.extractRequestParameters(request);
ensureSecureAccess(reqPathParts, pageRequestContextUtil.isRemoteViewer());
setAdditionalResponseHeaders(response);
doProcess(request, response, docPageController, docPathParts);
} catch (Exception e) {
e.printStackTrace();
writeExceptionResponse(request, response, e);
} finally {
response.close();
}
}
private void setAdditionalResponseHeaders(ClientResponse response) throws UnifyException {
Map additionalResponseHeaders = uiControllerUtil.getAdditionalResponseHeaders();
for (Map.Entry entry : additionalResponseHeaders.entrySet()) {
response.setMetaData(entry.getKey(), entry.getValue());
}
if (uiControllerUtil.isCSPNonce()) {
String policy = "default-src 'self'; script-src 'nonce-" + pageRequestContextUtil.getNonce()
+ "' 'unsafe-inline' 'strict-dynamic' 'self';";
response.setMetaData("Content-Security-Policy", policy);
}
}
@Override
public boolean isReadOnly() {
return readOnly;
}
@Override
public boolean isResetOnWrite() {
return resetOnWrite;
}
@Override
protected void onInitialize() throws UnifyException {
super.onInitialize();
}
protected PageRequestContextUtil getPageRequestContextUtil() throws UnifyException {
return pageRequestContextUtil;
}
protected PageManager getPageManager() {
return pageManager;
}
protected PathInfoRepository getPathInfoRepository() {
return pathInfoRepository;
}
protected ResponseWriterPool getResponseWriterPool() {
return responseWriterPool;
}
protected UIControllerUtil getUIControllerUtil() {
return uiControllerUtil;
}
protected abstract DataTransferParam getDataTransferParam() throws UnifyException;
protected abstract void doProcess(ClientRequest request, ClientResponse response,
PageController docPageController, ControllerPathParts docPathParts) throws UnifyException;
protected class DataTransferParam {
private UIControllerInfo uiControllerInfo;
private Class validationClass;
private Class validationIdClass;
public DataTransferParam(UIControllerInfo uiControllerInfo, Class validationClass,
Class validationIdClass) {
this.uiControllerInfo = uiControllerInfo;
this.validationClass = validationClass;
this.validationIdClass = validationIdClass;
}
public DataTransferParam(UIControllerInfo uiControllerInfo) {
this.uiControllerInfo = uiControllerInfo;
}
public UIControllerInfo getUIControllerInfo() {
return uiControllerInfo;
}
public Class getValidationClass() {
return validationClass;
}
public Class getValidationIdClass() {
return validationIdClass;
}
}
protected DataTransfer prepareDataTransfer(ClientRequest request) throws UnifyException {
String actionId = (String) request.getParameter(PageRequestParameterConstants.VALIDATION_ACTION);
Map transferBlocks = null;
DataTransferParam dataTransferParam = getDataTransferParam();
for (String transferId : request.getParameterNames()) {
if (skipOnPopulateSet.contains(transferId)) {
continue;
}
Object values = request.getParameter(transferId);
if (PageRequestParameterConstants.REFRESH.equals(transferId)) {
String[] strings = null;
if (values instanceof String[]) {
strings = (String[]) values;
} else {
strings = new String[] { (String) values };
}
for (int i = 0; i < strings.length; i++) {
String pageName = DataTransferUtils.stripTransferDataIndexPart(strings[i]);
strings[i] = pageManager.getLongName(pageName);
}
pageRequestContextUtil.setResponseRefreshPanels(strings);
continue;
}
if (PageRequestParameterConstants.COMMAND.equals(transferId)) {
if (!(values instanceof String)) {
throw new UnifyException(UnifyWebUIErrorConstants.MULTIPLE_COMMAND_PARAMETERS_IN_REQUEST);
}
String[] commandElements = ((String) values).split("->");
DataTransferBlock transferBlock = DataTransferUtils.createTransferBlock(commandElements[0]);
String parentLongName = pageManager.getLongName(transferBlock.getId());
RequestCommand requestCommand = new RequestCommand(transferBlock, parentLongName, commandElements[1]);
pageRequestContextUtil.setRequestCommand(requestCommand);
continue;
}
if (PageRequestParameterConstants.COMMAND_TAG.equals(transferId)) {
if (!(values instanceof String)) {
throw new UnifyException(UnifyWebUIErrorConstants.MULTIPLE_COMMAND_PARAMETERS_IN_REQUEST);
}
pageRequestContextUtil.setRequestCommandTag((String) values);
continue;
}
if (PageRequestParameterConstants.TRIGGER_WIDGETID.equals(transferId)) {
if (!(values instanceof String)) {
throw new UnifyException(UnifyWebUIErrorConstants.MULTIPLE_COMMAND_PARAMETERS_IN_REQUEST);
}
pageRequestContextUtil.setTriggerWidgetId((String) values);
continue;
}
if (transferBlocks == null) {
transferBlocks = new HashMap();
}
DataTransferHeader header = new DataTransferHeader(values);
DataTransferBlock transferBlock = DataTransferUtils.createTransferBlock(transferId, header);
String id = transferBlock.getId();
header.setLongName(pageManager.getLongName(id));
header.setBindingInfo(dataTransferParam.getUIControllerInfo().getPropertyInfo(id));
DataTransferBlock eldestBlock = transferBlocks.get(id);
if (eldestBlock == null) {
transferBlocks.put(id, transferBlock);
} else {
transferBlock.setSiblingBlock(eldestBlock.getSiblingBlock());
eldestBlock.setSiblingBlock(transferBlock);
}
}
return new DataTransfer(dataTransferParam.getValidationClass(), dataTransferParam.getValidationIdClass(),
actionId, transferBlocks);
}
protected void populate(DataTransfer dataTransfer) throws UnifyException {
if (!isReadOnly()) {
logDebug("Populating controller [{0}]", getName());
// Reset first
if (isResetOnWrite()) {
reset();
}
// Populate controller
for (DataTransferBlock dataTransferBlock : dataTransfer.getDataTransferBlocks()) {
do {
logDebug("Populating widget [{0}] with value [{1}] using transfer block [{2}]...",
dataTransferBlock.getLongName(), dataTransferBlock.getDebugValue(), dataTransferBlock);
populate(dataTransferBlock);
dataTransferBlock = dataTransferBlock.getSiblingBlock();
} while (dataTransferBlock != null);
}
logDebug("Controller population completed [{0}]", getName());
}
}
@SuppressWarnings("unchecked")
protected void writeResponse(ResponseWriter writer, Page page, Result result) throws UnifyException {
if (MimeType.APPLICATION_JSON.equals(result.getMimeType())) {
writer.write("{\"jsonResp\":[");
boolean appendSym = false;
for (PageControllerResponse pageControllerResponse : result.getResponses()) {
if (appendSym) {
writer.write(',');
} else {
appendSym = true;
}
pageControllerResponse.generate(writer, page);
}
writer.write("]");
List alwaysPushList = (List) getRequestAttribute(
UnifyCoreRequestAttributeConstants.ALWAYS_PUSH_COMPOMENT_LIST);
if (!DataUtils.isBlank(alwaysPushList)) {
Set _alwaysPush = new HashSet();
for (String pId : alwaysPushList) {
_alwaysPush.addAll(pageManager.getExpandedReferences(pId));
}
writer.write(",\"allPush\":").writeJsonArray(_alwaysPush);
}
if (pageRequestContextUtil.isRemoteViewer()) {
writer.write(",\"remoteView\":{");
writer.write("\"view\":\"").write(pageRequestContextUtil.getRemoteViewer()).write("\"}");
}
writer.write(",\"scrollReset\":").write(pageRequestContextUtil.isContentScrollReset());
writer.write("}");
} else {
for (PageControllerResponse pageControllerResponse : result.getResponses()) {
pageControllerResponse.generate(writer, page);
}
}
}
private void writeExceptionResponse(ClientRequest request, ClientResponse response, Exception e)
throws UnifyException {
logError(e);
if (response.isOutUsed()) {
if (e instanceof UnifyException) {
throw (UnifyException) e;
} else {
throw new UnifyOperationException(e);
}
}
// Set exception attributes in session context.
boolean loginRequired = false;
if (e instanceof UnifyException) {
String errorCode = ((UnifyException) e).getUnifyError().getErrorCode();
loginRequired = UnifyWebErrorConstants.LOGIN_REQUIRED.equals(errorCode)
|| UnifyCoreErrorConstants.UNKNOWN_PAGE_NAME.equals(errorCode)
|| SystemUtils.isForceLogoutErrorCode(errorCode);
}
String message = getExceptionMessage(LocaleType.SESSION, e);
setSessionAttribute(SystemInfoConstants.LOGIN_REQUIRED_FLAG, loginRequired);
setSessionAttribute(SystemInfoConstants.EXCEPTION_MESSAGE_KEY, message);
String trace = StringUtils.getPrintableStackTrace(e);
setSessionAttribute(SystemInfoConstants.EXCEPTION_STACKTRACE_KEY, trace);
// Generate exception response
ResponseWriter writer = responseWriterPool.getResponseWriter(request);
try {
PageController pageController = null;
ControllerPathParts respPathParts = null;
Page page = null;
Result result = null;
if (StringUtils.isBlank((String) request.getParameter(PageRequestParameterConstants.DOCUMENT))
&& !pageRequestContextUtil.isRemoteViewer()) {
respPathParts = pathInfoRepository
.getControllerPathParts(SystemInfoConstants.UNAUTHORIZED_CONTROLLER_NAME);
pageController = (PageController) getControllerFinder().findController(respPathParts);
page = uiControllerUtil.loadRequestPage(respPathParts);
page.setWidgetVisible("stackTrace", !loginRequired && !uiControllerUtil.isHideErrorTrace());
result = uiControllerUtil.getPageControllerInfo(pageController.getName())
.getResult(ResultMappingConstants.INDEX);
} else {
respPathParts = pathInfoRepository
.getControllerPathParts(SystemInfoConstants.SYSTEMINFO_CONTROLLER_NAME);
pageController = (PageController) getControllerFinder().findController(respPathParts);
page = uiControllerUtil.loadRequestPage(respPathParts);
page.setWidgetVisible("stackTrace", !loginRequired && !uiControllerUtil.isHideErrorTrace());
result = uiControllerUtil.getPageControllerInfo(pageController.getName())
.getResult(SystemInfoConstants.SHOW_SYSTEM_EXCEPTION_MAPPING);
}
pageRequestContextUtil.setResponsePathParts(respPathParts);
writeResponse(writer, page, result);
response.setContentType(result.getMimeType().template());
writer.writeTo(response.getWriter());
} catch (UnifyException e1) {
throw e1;
} catch (Exception e1) {
e1.printStackTrace();
throwOperationErrorException(e1);
} finally {
responseWriterPool.restore(writer);
}
}
}