/*
* Copyright (c) 2010-2016 Evolveum
*
* 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.evolveum.midpoint.web.page.admin.resources;
import com.evolveum.midpoint.gui.api.model.LoadableModel;
import com.evolveum.midpoint.gui.api.page.PageBase;
import com.evolveum.midpoint.gui.api.util.WebComponentUtil;
import com.evolveum.midpoint.model.api.ModelExecuteOptions;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismObjectDefinition;
import com.evolveum.midpoint.prism.PrismReference;
import com.evolveum.midpoint.prism.PrismReferenceValue;
import com.evolveum.midpoint.prism.delta.ObjectDelta;
import com.evolveum.midpoint.prism.marshaller.QueryConvertor;
import com.evolveum.midpoint.prism.query.ObjectFilter;
import com.evolveum.midpoint.prism.query.ObjectQuery;
import com.evolveum.midpoint.prism.schema.SchemaRegistry;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.security.api.AuthorizationConstants;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.Holder;
import com.evolveum.midpoint.util.exception.*;
import com.evolveum.midpoint.util.logging.LoggingUtils;
import com.evolveum.midpoint.web.application.AuthorizationAction;
import com.evolveum.midpoint.web.application.PageDescriptor;
import com.evolveum.midpoint.web.component.AjaxButton;
import com.evolveum.midpoint.web.component.AjaxSubmitButton;
import com.evolveum.midpoint.web.component.AceEditor;
import com.evolveum.midpoint.web.page.admin.dto.ObjectViewDto;
import com.evolveum.midpoint.web.util.OnePageParameterEncoder;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ConnectorType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType;
import org.apache.commons.lang.StringUtils;
import org.apache.wicket.RestartResponseException;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxCheckBox;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.util.string.StringValue;
import java.util.List;
/**
* @author lazyman
*
* TODO - delete this page when ResourceWizard is fully functional and tested
*/
@PageDescriptor(url = "/admin/resource/edit", encoder = OnePageParameterEncoder.class, action = {
@AuthorizationAction(actionUri = PageAdminResources.AUTH_RESOURCE_ALL,
label = PageAdminResources.AUTH_RESOURCE_ALL_LABEL,
description = PageAdminResources.AUTH_RESOURCE_ALL_DESCRIPTION),
@AuthorizationAction(actionUri = AuthorizationConstants.AUTZ_UI_RESOURCE_EDIT_URL,
label = "PageResourceEdit.auth.resourceEdit.label",
description = "PageResourceEdit.auth.resourceEdit.description")})
@Deprecated
public class PageResourceEdit extends PageAdminResources {
private static final String DOT_CLASS = PageResourceEdit.class.getName() + ".";
private static final String OPERATION_SAVE_RESOURCE = DOT_CLASS + "saveResource";
private static final String ID_MAIN_FORM = "mainForm";
private static final String ID_EDIT = "edit";
private static final String ID_ACE_EDITOR = "aceEditor";
private static final String ID_SAVE_BUTTON = "saveButton";
private static final String ID_BACK_BUTTON = "backButton";
private IModel<ObjectViewDto> model;
public PageResourceEdit() {
model = new LoadableModel<ObjectViewDto>(false) {
@Override
protected ObjectViewDto load() {
return loadResource();
}
};
initLayout();
}
@Override
protected IModel<String> createPageTitleModel() {
return new LoadableModel<String>(false) {
@Override
protected String load() {
if (!isEditing()) {
return PageResourceEdit.super.createPageTitleModel().getObject();
}
String name = model.getObject().getName();
return PageBase.createStringResourceStatic(PageResourceEdit.this, "page.title.editResource", name).getString();
// return new StringResourceModel("page.title.editResource", PageResourceEdit.this, null, null, name).getString();
}
};
}
private ObjectViewDto loadResource() {
if (!isEditing()) {
return new ObjectViewDto();
}
ObjectViewDto dto;
try {
PrismObject<ResourceType> resource = loadResource(null);
String xml = getPrismContext().serializeObjectToString(resource, PrismContext.LANG_XML);
dto = new ObjectViewDto(resource.getOid(), WebComponentUtil.getName(resource), resource, xml);
} catch (Exception ex) {
LoggingUtils.logUnexpectedException(LOGGER, "Couldn't load resource", ex);
throw new RestartResponseException(PageResources.class);
}
return dto;
}
private void initLayout() {
Form mainForm = new Form(ID_MAIN_FORM);
add(mainForm);
final IModel<Boolean> editable = new LoadableModel<Boolean>(false) {
@Override
protected Boolean load() {
return !isEditing();
}
};
mainForm.add(new AjaxCheckBox(ID_EDIT, editable) {
@Override
protected void onUpdate(AjaxRequestTarget target) {
editPerformed(target, editable.getObject());
}
});
AceEditor editor = new AceEditor(ID_ACE_EDITOR, new PropertyModel<String>(model, ObjectViewDto.F_XML));
editor.setReadonly(new LoadableModel<Boolean>(false) {
@Override
protected Boolean load() {
return isEditing();
}
});
mainForm.add(editor);
initButtons(mainForm);
}
private void initButtons(final Form mainForm) {
AjaxSubmitButton saveButton = new AjaxSubmitButton(ID_SAVE_BUTTON,
createStringResource("PageBase.button.save")) {
@Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
savePerformed(target);
}
@Override
protected void onError(AjaxRequestTarget target, Form<?> form) {
target.add(getFeedbackPanel());
}
};
mainForm.add(saveButton);
AjaxButton backButton = new AjaxButton(ID_BACK_BUTTON, createStringResource("PageBase.button.back")) {
@Override
public void onClick(AjaxRequestTarget target) {
setResponsePage(new PageResources(false));
}
};
mainForm.add(backButton);
}
private boolean isEditing() {
StringValue resourceOid = getPageParameters().get(OnePageParameterEncoder.PARAMETER);
if (resourceOid == null || StringUtils.isEmpty(resourceOid.toString())) {
return false;
}
return true;
}
private void editPerformed(AjaxRequestTarget target, boolean editable) {
AceEditor editor = (AceEditor) get(createComponentPath(ID_MAIN_FORM, ID_ACE_EDITOR));
editor.setReadonly(!editable);
editor.refreshReadonly(target);
}
private void savePerformed(AjaxRequestTarget target) {
ObjectViewDto dto = model.getObject();
if (StringUtils.isEmpty(dto.getXml())) {
error(getString("pageResourceEdit.message.emptyXml"));
target.add(getFeedbackPanel());
return;
}
Task task = createSimpleTask(OPERATION_SAVE_RESOURCE);
OperationResult result = task.getResult();
try {
Holder<PrismObject<ResourceType>> objectHolder = new Holder<PrismObject<ResourceType>>(null);
validateObject(dto.getXml(), objectHolder, PrismContext.LANG_XML, false, result);
if (result.isAcceptable()) {
PrismObject<ResourceType> newResource = objectHolder.getValue();
updateConnectorRef(newResource, task, result);
if (!isEditing()) {
//we're adding new resource
ObjectDelta delta = ObjectDelta.createAddDelta(newResource);
getModelService().executeChanges(WebComponentUtil.createDeltaCollection(delta), null, task, result);
} else {
//we're editing existing resource
PrismObject<ResourceType> oldResource = dto.getObject();
ObjectDelta<ResourceType> delta = oldResource.diff(newResource);
getModelService().executeChanges(WebComponentUtil.createDeltaCollection(delta),
ModelExecuteOptions.createRaw(), task, result);
}
result.computeStatus();
}
} catch (Exception ex) {
LoggingUtils.logUnexpectedException(LOGGER, "Couldn't save resource", ex);
result.recordFatalError("Couldn't save resource.", ex);
}
if (WebComponentUtil.isSuccessOrHandledError(result)) {
showResult(result);
setResponsePage(new PageResources(false));
} else {
showResult(result);
target.add(getFeedbackPanel());
}
}
/**
* Method which attempts to resolve connector reference filter to actual connector (if necessary).
*
* @param resource {@link PrismObject} resource
*/
private void updateConnectorRef(PrismObject<ResourceType> resource, Task task, OperationResult result)
throws SchemaException, ObjectNotFoundException, SecurityViolationException, CommunicationException,
ConfigurationException {
if (resource == null) {
return;
}
PrismReference resourceRef = resource.findReference(ResourceType.F_CONNECTOR_REF);
if (resourceRef == null || resourceRef.getValue() == null) {
return;
}
PrismReferenceValue refValue = resourceRef.getValue();
if (StringUtils.isNotEmpty(refValue.getOid())) {
return;
}
if (refValue.getFilter() == null) {
return;
}
SchemaRegistry registry = getPrismContext().getSchemaRegistry();
PrismObjectDefinition objDef = registry.findObjectDefinitionByCompileTimeClass(ConnectorType.class);
ObjectFilter filter = QueryConvertor.parseFilter(refValue.getFilter(), objDef);
List<PrismObject<ConnectorType>> connectors = getModelService().searchObjects(ConnectorType.class,
ObjectQuery.createObjectQuery(filter), null, task, result);
if (connectors.size() != 1) {
return;
}
PrismObject<ConnectorType> connector = connectors.get(0);
refValue.setOid(connector.getOid());
refValue.setTargetType(ConnectorType.COMPLEX_TYPE);
refValue.setFilter(null);
}
}