/* * Copyright (c) 2010-2015 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 java.util.ArrayList; import java.util.Collection; import java.util.List; import com.evolveum.midpoint.web.application.Url; import com.evolveum.midpoint.web.component.data.column.DoubleButtonColumn; import com.evolveum.midpoint.web.component.data.column.InlineMenuButtonColumn; import com.evolveum.midpoint.web.component.dialog.ConfirmationPanel; import com.evolveum.midpoint.web.component.search.*; import com.evolveum.midpoint.web.session.PageStorage; import com.evolveum.midpoint.web.session.SessionStorage; import com.evolveum.midpoint.xml.ns._public.common.common_3.SearchBoxModeType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; import org.apache.commons.lang.StringUtils; import org.apache.wicket.Component; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn; import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.model.AbstractReadOnlyModel; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; import org.apache.wicket.request.mapper.parameter.PageParameters; import com.evolveum.midpoint.gui.api.GuiStyleConstants; import com.evolveum.midpoint.gui.api.component.MainObjectListPanel; 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.prism.delta.ObjectDelta; import com.evolveum.midpoint.schema.GetOperationOptions; import com.evolveum.midpoint.schema.RetrieveOption; import com.evolveum.midpoint.schema.SelectorOptions; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.result.OperationResultStatus; import com.evolveum.midpoint.security.api.AuthorizationConstants; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.util.logging.LoggingUtils; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.web.application.AuthorizationAction; import com.evolveum.midpoint.web.application.PageDescriptor; import com.evolveum.midpoint.web.component.data.Table; import com.evolveum.midpoint.web.component.data.column.ColumnMenuAction; import com.evolveum.midpoint.web.component.data.column.InlineMenuHeaderColumn; import com.evolveum.midpoint.web.component.menu.cog.InlineMenuItem; import com.evolveum.midpoint.web.component.util.SelectableBean; import com.evolveum.midpoint.web.page.admin.configuration.PageDebugView; import com.evolveum.midpoint.web.page.admin.configuration.component.HeaderMenuAction; import com.evolveum.midpoint.web.session.ResourcesStorage; import com.evolveum.midpoint.web.session.UserProfileStorage.TableId; import com.evolveum.midpoint.web.util.OnePageParameterEncoder; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; /** * @author lazyman */ @PageDescriptor( urls = { @Url(mountUrl = "/admin/resources", matchUrlForSecurity = "/admin/resources") }, action = { @AuthorizationAction(actionUri = PageAdminResources.AUTH_RESOURCE_ALL, label = PageAdminResources.AUTH_RESOURCE_ALL_LABEL, description = PageAdminResources.AUTH_RESOURCE_ALL_DESCRIPTION), @AuthorizationAction(actionUri = AuthorizationConstants.AUTZ_UI_RESOURCES_URL, label = "PageResources.auth.resources.label", description = "PageResources.auth.resources.description") }) public class PageResources extends PageAdminResources { private static final long serialVersionUID = 1L; private static final Trace LOGGER = TraceManager.getTrace(PageResources.class); private static final String DOT_CLASS = PageResources.class.getName() + "."; private static final String OPERATION_TEST_RESOURCE = DOT_CLASS + "testResource"; private static final String OPERATION_DELETE_RESOURCES = DOT_CLASS + "deleteResources"; private static final String ID_MAIN_FORM = "mainForm"; private static final String ID_TABLE = "table"; private static final String ID_CONNECTOR_TABLE = "connectorTable"; private IModel<Search> searchModel; private ResourceType singleDelete; public PageResources() { this(true); } public PageResources(boolean clearSessionPaging) { this(clearSessionPaging, ""); } public PageResources(String searchText) { this(true, searchText); } public PageResources(boolean clearSessionPaging, String searchText) { searchModel = new LoadableModel<Search>(false) { private static final long serialVersionUID = 1L; @Override protected Search load() { ResourcesStorage storage = getSessionStorage().getResources(); Search dto = storage.getSearch(); if (dto == null) { dto = SearchFactory.createSearch(ResourceType.class, getPrismContext(), getModelInteractionService()); } return dto; } }; if (StringUtils.isNotEmpty(searchText)){ initSearch(searchText); } initLayout(); } private void initSearch(String text){ PageStorage storage = getSessionStorage().getPageStorageMap().get(SessionStorage.KEY_RESOURCES); if (storage == null) { storage = getSessionStorage().initPageStorage(SessionStorage.KEY_RESOURCES); } Search search = SearchFactory.createSearch(ResourceType.class, getPrismContext(), getModelInteractionService()); if (SearchBoxModeType.FULLTEXT.equals(search.getSearchType())){ search.setFullText(text); } else if (search.getItems() != null && search.getItems().size() > 0){ SearchItem searchItem = search.getItems().get(0); searchItem.getValues().add(new SearchValue<>(text)); } storage.setSearch(search); getSessionStorage().getPageStorageMap().put(SessionStorage.KEY_RESOURCES, storage); } private void initLayout() { Form mainForm = new Form(ID_MAIN_FORM); add(mainForm); Collection<SelectorOptions<GetOperationOptions>> options = SelectorOptions .createCollection(GetOperationOptions.createNoFetch()); options.add(SelectorOptions.create(ResourceType.F_CONNECTOR_REF, GetOperationOptions.createRetrieve(RetrieveOption.INCLUDE))); MainObjectListPanel<ResourceType> resourceListPanel = new MainObjectListPanel<ResourceType>(ID_TABLE, ResourceType.class, TableId.TABLE_RESOURCES, options, this) { private static final long serialVersionUID = 1L; @Override protected List<InlineMenuItem> createInlineMenu() { return PageResources.this.createRowMenuItems(false); } @Override protected List<IColumn<SelectableBean<ResourceType>, String>> createColumns() { return PageResources.this.initResourceColumns(); } @Override protected IColumn<SelectableBean<ResourceType>, String> createActionsColumn() { return PageResources.this.createResourceActionsColumn(); } @Override protected void objectDetailsPerformed(AjaxRequestTarget target, ResourceType object) { PageResources.this.resourceDetailsPerformed(target, object.getOid()); } @Override protected void newObjectPerformed(AjaxRequestTarget target) { navigateToNext(PageResourceWizard.class); } }; resourceListPanel.setOutputMarkupId(true); resourceListPanel.setAdditionalBoxCssClasses(GuiStyleConstants.CLASS_OBJECT_RESOURCE_BOX_CSS_CLASSES); mainForm.add(resourceListPanel); } private List<InlineMenuItem> createRowMenuItems(boolean isHeader) { List<InlineMenuItem> menuItems = new ArrayList<>(); menuItems.add(new InlineMenuItem(createStringResource("PageResources.inlineMenuItem.test"), new Model<Boolean>(false), new Model<Boolean>(false), false, new ColumnMenuAction<SelectableBean<ResourceType>>() { @Override public void onClick(AjaxRequestTarget target) { SelectableBean<ResourceType> rowDto = getRowModel().getObject(); testResourcePerformed(target, rowDto.getValue()); } }, isHeader ? InlineMenuItem.RESOURCE_INLINE_MENU_ITEM_ID.HEADER_TEST_CONNECTION.getMenuItemId() : InlineMenuItem.RESOURCE_INLINE_MENU_ITEM_ID.TEST_CONNECTION.getMenuItemId(), GuiStyleConstants.CLASS_TEST_CONNECTION_MENU_ITEM, DoubleButtonColumn.BUTTON_COLOR_CLASS.INFO.toString())); menuItems.add(new InlineMenuItem(createStringResource("PageBase.button.delete"), new Model<Boolean>(true), new Model<Boolean>(true), false, new ColumnMenuAction<SelectableBean<ResourceType>>() { @Override public void onClick(AjaxRequestTarget target) { if (getRowModel() == null){ deleteResourcePerformed(target, null); } else { SelectableBean<ResourceType> rowDto = getRowModel().getObject(); deleteResourcePerformed(target, rowDto.getValue()); } } }, isHeader ? InlineMenuItem.RESOURCE_INLINE_MENU_ITEM_ID.HEADER_DELETE.getMenuItemId() : InlineMenuItem.RESOURCE_INLINE_MENU_ITEM_ID.DELETE_RESOURCE.getMenuItemId(), GuiStyleConstants.CLASS_DELETE_MENU_ITEM, DoubleButtonColumn.BUTTON_COLOR_CLASS.DANGER.toString())); menuItems.add(new InlineMenuItem(createStringResource("pageResources.inlineMenuItem.deleteSyncToken"), isHeader ? new Model<Boolean>(false) : new Model<Boolean>(true), isHeader ? new Model<Boolean>(false) : new Model<Boolean>(true), false, new ColumnMenuAction<SelectableBean<ResourceType>>() { @Override public void onClick(AjaxRequestTarget target) { SelectableBean<ResourceType> rowDto = getRowModel().getObject(); deleteResourceSyncTokenPerformed(target, rowDto.getValue()); } })); menuItems.add(new InlineMenuItem(createStringResource("pageResources.inlineMenuItem.editResource"), isHeader ? new Model<Boolean>(false) : new Model<Boolean>(true), isHeader ? new Model<Boolean>(false) : new Model<Boolean>(true), false, new ColumnMenuAction<SelectableBean<ResourceType>>() { @Override public void onClick(AjaxRequestTarget target) { SelectableBean<ResourceType> rowDto = getRowModel().getObject(); editResourcePerformed(rowDto.getValue()); } })); menuItems.add(new InlineMenuItem(createStringResource("pageResources.button.editAsXml"), new Model<Boolean>(false), new Model<Boolean>(false), false, new ColumnMenuAction<SelectableBean<ResourceType>>() { @Override public void onClick(AjaxRequestTarget target) { SelectableBean<ResourceType> rowDto = getRowModel().getObject(); editAsXmlPerformed(rowDto.getValue()); } }, InlineMenuItem.RESOURCE_INLINE_MENU_ITEM_ID.EDIT_XML.getMenuItemId(), GuiStyleConstants.CLASS_EDIT_MENU_ITEM, DoubleButtonColumn.BUTTON_COLOR_CLASS.INFO.toString())); return menuItems; } private List<IColumn<SelectableBean<ResourceType>, String>> initResourceColumns() { List<IColumn<SelectableBean<ResourceType>, String>> columns = new ArrayList<>(); columns.add(new PropertyColumn(createStringResource("pageResources.connectorType"), SelectableBean.F_VALUE + ".connector.connectorType")); columns.add(new PropertyColumn(createStringResource("pageResources.version"), SelectableBean.F_VALUE + ".connector.connectorVersion")); return columns; } private IColumn<SelectableBean<ResourceType>, String> createResourceActionsColumn() { return new InlineMenuButtonColumn<SelectableBean<ResourceType>>(createRowMenuItems(false), 2, PageResources.this){ @Override protected int getHeaderNumberOfButtons() { return 1; } @Override protected List<InlineMenuItem> getHeaderMenuItems() { return createRowMenuItems(true); } }; } private void resourceDetailsPerformed(AjaxRequestTarget target, String oid) { clearSessionStorageForResourcePage(); PageParameters parameters = new PageParameters(); parameters.add(OnePageParameterEncoder.PARAMETER, oid); navigateToNext(PageResource.class, parameters); } private List<ResourceType> isAnyResourceSelected(AjaxRequestTarget target, ResourceType single) { List<ResourceType> selected = null; if (single != null) { selected = new ArrayList<>(1); selected.add(single); return selected; } selected = getResourceTable().getSelectedObjects(); if (selected.size() < 1) { warn(createStringResource("pageResources.message.noResourceSelected")); } return selected; } private void deleteResourcePerformed(AjaxRequestTarget target, ResourceType single) { List<ResourceType> selected = isAnyResourceSelected(target, single); singleDelete = single; if (selected.isEmpty()) { return; } ConfirmationPanel dialog = new ConfirmationPanel(((PageBase)getPage()).getMainPopupBodyId(), createDeleteConfirmString("pageResources.message.deleteResourceConfirm", "pageResources.message.deleteResourcesConfirm", true)){ @Override public void yesPerformed(AjaxRequestTarget target) { ((PageBase)getPage()).hideMainPopup(target); deleteResourceConfirmedPerformed(target); } }; ((PageBase)getPage()).showMainPopup(dialog, target); } private MainObjectListPanel<ResourceType> getResourceTable() { return (MainObjectListPanel<ResourceType>) get(createComponentPath(ID_MAIN_FORM, ID_TABLE)); } private Table getConnectorHostTable() { return (Table) get(createComponentPath(ID_MAIN_FORM, ID_CONNECTOR_TABLE)); } /** * @param oneDeleteKey * message if deleting one item * @param moreDeleteKey * message if deleting more items * @param resources * if true selecting resources if false selecting from hosts */ private IModel<String> createDeleteConfirmString(final String oneDeleteKey, final String moreDeleteKey, final boolean resources) { return new AbstractReadOnlyModel<String>() { @Override public String getObject() { List selected = new ArrayList(); if (singleDelete != null) { selected.add(singleDelete); } else { selected = getResourceTable().getSelectedObjects(); } switch (selected.size()) { case 1: Object first = selected.get(0); String name = WebComponentUtil.getName(((ResourceType) first)); return createStringResource(oneDeleteKey, name).getString(); default: return createStringResource(moreDeleteKey, selected.size()).getString(); } } }; } private void deleteResourceConfirmedPerformed(AjaxRequestTarget target) { List<ResourceType> selected = new ArrayList<>(); if (singleDelete != null) { selected.add(singleDelete); } else { selected = getResourceTable().getSelectedObjects(); } OperationResult result = new OperationResult(OPERATION_DELETE_RESOURCES); for (ResourceType resource : selected) { try { Task task = createSimpleTask(OPERATION_DELETE_RESOURCES); ObjectDelta<ResourceType> delta = ObjectDelta.createDeleteDelta(ResourceType.class, resource.getOid(), getPrismContext()); getModelService().executeChanges(WebComponentUtil.createDeltaCollection(delta), null, task, result); } catch (Exception ex) { result.recordPartialError("Couldn't delete resource.", ex); LoggingUtils.logUnexpectedException(LOGGER, "Couldn't delete resource", ex); } } result.recomputeStatus(); if (result.isSuccess()) { result.recordStatus(OperationResultStatus.SUCCESS, "The resource(s) have been successfully deleted."); } getResourceTable().clearCache(); showResult(result); target.add(getFeedbackPanel(), (Component) getResourceTable()); } private void testResourcePerformed(AjaxRequestTarget target, ResourceType resourceType) { OperationResult result = new OperationResult(OPERATION_TEST_RESOURCE); // SelectableBean<ResourceType> dto = rowModel.getObject(); // ResourceType resourceType = dto.getValue(); if (StringUtils.isEmpty(resourceType.getOid())) { result.recordFatalError("Resource oid not defined in request"); } Task task = createSimpleTask(OPERATION_TEST_RESOURCE); try { result = getModelService().testResource(resourceType.getOid(), task); // ResourceController.updateResourceState(resourceType.getState(), // result); // todo de-duplicate code (see the same operation in PageResource) // this provides some additional tests, namely a test for schema // handling section getModelService().getObject(ResourceType.class, resourceType.getOid(), null, task, result); } catch (Exception ex) { result.recordFatalError("Failed to test resource connection", ex); } // a bit of hack: result of TestConnection contains a result of // getObject as a subresult // so in case of TestConnection succeeding we recompute the result to // show any (potential) getObject problems if (result.isSuccess()) { result.recomputeStatus(); } // if (!result.isSuccess()) { showResult(result); target.add(getFeedbackPanel()); // } target.add(getResourceTable()); } private void deleteResourceSyncTokenPerformed(AjaxRequestTarget target, ResourceType resourceType) { deleteSyncTokenPerformed(target, resourceType); } private void editResourcePerformed(ResourceType resourceType) { PageParameters parameters = new PageParameters(); parameters.add(OnePageParameterEncoder.PARAMETER, resourceType.getOid()); navigateToNext(new PageResourceWizard(parameters)); } private void editAsXmlPerformed(ResourceType resourceType) { PageParameters parameters = new PageParameters(); parameters.add(PageDebugView.PARAM_OBJECT_ID, resourceType.getOid()); parameters.add(PageDebugView.PARAM_OBJECT_TYPE, ResourceType.class.getSimpleName()); navigateToNext(PageDebugView.class, parameters); } private void clearSessionStorageForResourcePage() { ((PageBase) getPage()).getSessionStorage().clearResourceContentStorage(); } }