/*
* Copyright (c) 2013-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.model.impl;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo;
import javax.xml.bind.JAXBException;
import javax.xml.namespace.QName;
import org.apache.commons.configuration.SystemConfiguration;
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.Validate;
import org.apache.cxf.jaxrs.ext.MessageContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.evolveum.midpoint.model.api.ModelCompareOptions;
import com.evolveum.midpoint.model.api.ModelDiagnosticService;
import com.evolveum.midpoint.model.api.ModelExecuteOptions;
import com.evolveum.midpoint.model.api.ModelInteractionService;
import com.evolveum.midpoint.model.api.ModelService;
import com.evolveum.midpoint.model.api.ScriptExecutionResult;
import com.evolveum.midpoint.model.api.ScriptingService;
import com.evolveum.midpoint.model.api.validator.ResourceValidator;
import com.evolveum.midpoint.model.api.validator.Scope;
import com.evolveum.midpoint.model.api.validator.ValidationResult;
import com.evolveum.midpoint.model.common.stringpolicy.ValuePolicyProcessor;
import com.evolveum.midpoint.model.impl.rest.PATCH;
import com.evolveum.midpoint.model.impl.security.SecurityHelper;
import com.evolveum.midpoint.model.impl.util.RestServiceUtil;
import com.evolveum.midpoint.prism.Item;
import com.evolveum.midpoint.prism.ItemDefinition;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismProperty;
import com.evolveum.midpoint.prism.PrismPropertyDefinition;
import com.evolveum.midpoint.prism.PrismValue;
import com.evolveum.midpoint.prism.crypto.EncryptionException;
import com.evolveum.midpoint.prism.crypto.Protector;
import com.evolveum.midpoint.prism.delta.ItemDelta;
import com.evolveum.midpoint.prism.delta.PropertyDelta;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.polystring.PolyString;
import com.evolveum.midpoint.prism.query.ObjectQuery;
import com.evolveum.midpoint.prism.query.QueryJaxbConvertor;
import com.evolveum.midpoint.prism.query.builder.QueryBuilder;
import com.evolveum.midpoint.schema.DeltaConvertor;
import com.evolveum.midpoint.schema.GetOperationOptions;
import com.evolveum.midpoint.schema.SelectorOptions;
import com.evolveum.midpoint.schema.constants.MidPointConstants;
import com.evolveum.midpoint.schema.constants.ObjectTypes;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.security.api.SecurityUtil;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.task.api.TaskManager;
import com.evolveum.midpoint.util.DOMUtil;
import com.evolveum.midpoint.util.MiscUtil;
import com.evolveum.midpoint.util.QNameUtil;
import com.evolveum.midpoint.util.exception.CommunicationException;
import com.evolveum.midpoint.util.exception.ConfigurationException;
import com.evolveum.midpoint.util.exception.ExpressionEvaluationException;
import com.evolveum.midpoint.util.exception.ObjectNotFoundException;
import com.evolveum.midpoint.util.exception.PolicyViolationException;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.exception.SecurityViolationException;
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.xml.ns._public.common.api_types_3.CompareResultType;
import com.evolveum.midpoint.xml.ns._public.common.api_types_3.ObjectListType;
import com.evolveum.midpoint.xml.ns._public.common.api_types_3.ObjectModificationType;
import com.evolveum.midpoint.xml.ns._public.common.api_types_3.PolicyItemDefinitionType;
import com.evolveum.midpoint.xml.ns._public.common.api_types_3.PolicyItemTargetType;
import com.evolveum.midpoint.xml.ns._public.common.api_types_3.PolicyItemsDefinitionType;
import com.evolveum.midpoint.xml.ns._public.common.api_types_3.ScriptOutputsType;
import com.evolveum.midpoint.xml.ns._public.common.api_types_3.SingleScriptOutputType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.CredentialsPolicyType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.LogFileContentType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.NodeType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationResultType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceObjectShadowChangeDescriptionType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.StringPolicyType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ValuePolicyType;
import com.evolveum.midpoint.xml.ns._public.model.model_3.ExecuteScriptsResponseType;
import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ItemListType;
import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ScriptingExpressionType;
import com.evolveum.prism.xml.ns._public.query_3.QueryType;
import com.evolveum.prism.xml.ns._public.types_3.PolyStringType;
import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType;
import com.evolveum.prism.xml.ns._public.types_3.RawType;
/**
* @author katkav
* @author semancik
*/
@Service
@Produces({"application/xml", "application/json", "application/yaml"})
public class ModelRestService {
public static final String CLASS_DOT = ModelRestService.class.getName() + ".";
public static final String OPERATION_REST_SERVICE = CLASS_DOT + "restService";
public static final String OPERATION_GET = CLASS_DOT + "get";
public static final String OPERATION_SELF = CLASS_DOT + "self";
public static final String OPERATION_ADD_OBJECT = CLASS_DOT + "addObject";
public static final String OPERATION_DELETE_OBJECT = CLASS_DOT + "deleteObject";
public static final String OPERATION_MODIFY_OBJECT = CLASS_DOT + "modifyObject";
public static final String OPERATION_NOTIFY_CHANGE = CLASS_DOT + "notifyChange";
public static final String OPERATION_FIND_SHADOW_OWNER = CLASS_DOT + "findShadowOwner";
public static final String OPERATION_SEARCH_OBJECTS = CLASS_DOT + "searchObjects";
public static final String OPERATION_IMPORT_FROM_RESOURCE = CLASS_DOT + "importFromResource";
public static final String OPERATION_TEST_RESOURCE = CLASS_DOT + "testResource";
public static final String OPERATION_SUSPEND_TASKS = CLASS_DOT + "suspendTasks";
public static final String OPERATION_SUSPEND_AND_DELETE_TASKS = CLASS_DOT + "suspendAndDeleteTasks";
public static final String OPERATION_RESUME_TASKS = CLASS_DOT + "resumeTasks";
public static final String OPERATION_SCHEDULE_TASKS_NOW = CLASS_DOT + "scheduleTasksNow";
public static final String OPERATION_EXECUTE_SCRIPT = CLASS_DOT + "executeScript";
public static final String OPERATION_COMPARE = CLASS_DOT + "compare";
public static final String OPERATION_GET_LOG_FILE_CONTENT = CLASS_DOT + "getLogFileContent";
public static final String OPERATION_GET_LOG_FILE_SIZE = CLASS_DOT + "getLogFileSize";
public static final String OPERATION_VALIDATE_VALUE = CLASS_DOT + "validateValue";
public static final String OPERATION_GENERATE_VALUE = CLASS_DOT + "generateValue";
private static final String CURRENT = "current";
private static final String VALIDATE = "validate";
@Autowired
private ModelCrudService model;
@Autowired
private ScriptingService scriptingService;
@Autowired
private ModelService modelService;
@Autowired
private ModelDiagnosticService modelDiagnosticService;
@Autowired
private ModelInteractionService modelInteraction;
@Autowired
private PrismContext prismContext;
@Autowired
private SecurityHelper securityHelper;
@Autowired
ValuePolicyProcessor policyProcessor;
@Autowired
private TaskManager taskManager;
@Autowired
private Protector protector;
@Autowired
private ResourceValidator resourceValidator;
private static final Trace LOGGER = TraceManager.getTrace(ModelRestService.class);
public static final long WAIT_FOR_TASK_STOP = 2000L;
public ModelRestService() {
// nothing to do
}
@POST
@Path("/{type}/{oid}/generate")
@Consumes({"application/xml", "application/json", "application/yaml"})
@Produces({"application/xml", "application/json", "application/yaml"})
public <O extends ObjectType> Response generateValue(@PathParam("type") String type,
@PathParam("oid") String oid, PolicyItemsDefinitionType policyItemsDefinition,
@Context MessageContext mc) {
Task task = RestServiceUtil.initRequest(mc);
OperationResult parentResult = task.getResult().createSubresult(OPERATION_GENERATE_VALUE);
Class<O> clazz = ObjectTypes.getClassFromRestType(type);
Response response = null;
if (policyItemsDefinition == null) {
LOGGER.error("Policy items definition must not be null");
parentResult.recordFatalError("Policy items definition must not be null");
ResponseBuilder builder = Response.status(Status.BAD_REQUEST).entity(parentResult);
return builder.build();
}
try {
PrismObject<O> object = model.getObject(clazz, oid, null, task, parentResult);
PrismObject<ValuePolicyType> valuePolicy = resolvePolicy(object, task, parentResult);
boolean executeImmediatelly = false;
Collection<PropertyDelta> propertyDeltas = new ArrayList<>();
for (PolicyItemDefinitionType policyItemDefinition : policyItemsDefinition
.getPolicyItemDefinition()) {
generateValue(object, valuePolicy, policyItemDefinition, task, parentResult);
if (BooleanUtils.isTrue(policyItemDefinition.isExecute())) {
executeImmediatelly = true;
ItemPath path = policyItemDefinition.getTarget().getPath().getItemPath();
PrismProperty item = object.findOrCreateProperty(path);
Object value = policyItemDefinition.getValue();
if (item.getDefinition() != null) {
if (item.getDefinition().getTypeName().equals(ProtectedStringType.COMPLEX_TYPE)) {
ProtectedStringType pst = new ProtectedStringType();
pst.setClearValue((String) policyItemDefinition.getValue());
value = pst;
} else if (item.getDefinition().getTypeName().equals(PolyStringType.COMPLEX_TYPE)) {
PolyString polyString = new PolyString((String) policyItemDefinition.getValue());
value = polyString;
}
}
PropertyDelta propertyDelta = PropertyDelta.createModificationReplaceProperty(path, object.getDefinition(), value);
propertyDeltas.add(propertyDelta);
}
}
if (executeImmediatelly) {
model.modifyObject(clazz, oid, propertyDeltas, null, task, parentResult);
}
ResponseBuilder responseBuilder = Response.ok(policyItemsDefinition);
response = responseBuilder.build();
} catch (Exception ex) {
parentResult.computeStatus();
response = RestServiceUtil.handleException(parentResult, ex);
}
parentResult.computeStatus();
finishRequest(task);
return response;
}
private <O extends ObjectType> PrismObject<ValuePolicyType> resolvePolicy(PrismObject<O> object, Task task, OperationResult parentResult) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, SecurityViolationException {
PrismObject<ValuePolicyType> valuePolicy = null;
if (object.getCompileTimeClass().isAssignableFrom(UserType.class)) {
CredentialsPolicyType policy = modelInteraction
.getCredentialsPolicy((PrismObject<UserType>) object, task, parentResult);
if (policy != null) {
if (policy.getPassword().getPasswordPolicyRef() != null) {
valuePolicy = model.getObject(ValuePolicyType.class,
policy.getPassword().getPasswordPolicyRef().getOid(), null, task, parentResult);
}
}
} else {
SystemConfigurationType systemConfigurationType = modelInteraction
.getSystemConfiguration(parentResult);
ObjectReferenceType policyRef = systemConfigurationType.getGlobalPasswordPolicyRef();
if (policyRef == null) {
return null;
}
valuePolicy = model.getObject(ValuePolicyType.class, policyRef.getOid(), null, task, parentResult);
}
return valuePolicy;
}
private <O extends ObjectType> void generateValue(PrismObject<O> object, PrismObject<ValuePolicyType> policy, PolicyItemDefinitionType policyItemDefinition, Task task, OperationResult result) throws ExpressionEvaluationException, SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException, SecurityViolationException {
PolicyItemTargetType target = policyItemDefinition.getTarget();
if (target == null || target.getPath() == null) {
LOGGER.error("Target item path must be defined");
result.recordFatalError("Target item path must be defined");
throw new SchemaException("Target item path must be defined");
}
ItemPath targetProperty = target.getPath().getItemPath();
StringPolicyType stringPolicy = null;
if (policyItemDefinition.getValuePolicyRef() != null) {
PrismObject<ValuePolicyType> valuePolicy = model.getObject(ValuePolicyType.class, policyItemDefinition.getValuePolicyRef().getOid(), null, task, result);
PrismObject<ValuePolicyType> policyOverride = valuePolicy.clone();
stringPolicy = policyOverride != null ? policyOverride.asObjectable().getStringPolicy() : null;
} else {
if (stringPolicy == null) {
SystemConfigurationType systemConfiguration = modelInteraction.getSystemConfiguration(result);
if (systemConfiguration.getGlobalPasswordPolicyRef() != null) {
PrismObject<ValuePolicyType> valuePolicy = model.getObject(ValuePolicyType.class, systemConfiguration.getGlobalPasswordPolicyRef().getOid(), null, task, result);
stringPolicy = valuePolicy != null ? valuePolicy.asObjectable().getStringPolicy() : null;
}
} else {
stringPolicy = policy != null ? policy.asObjectable().getStringPolicy() : null;
}
}
String newValue = policyProcessor.generate(targetProperty, stringPolicy, 10, object, "generating value for" + targetProperty, task, result);
policyItemDefinition.setValue(newValue);
}
@POST
@Path("/{type}/{oid}/validate")
@Consumes({"application/xml", "application/json", "application/yaml"})
@Produces({"application/xml", "application/json", "application/yaml"})
public <O extends ObjectType> Response validateValue(@PathParam("type") String type, @PathParam("oid") String oid, PolicyItemsDefinitionType policyItemsDefinition, @Context MessageContext mc) {
Task task = RestServiceUtil.initRequest(mc);
OperationResult parentResult = task.getResult().createSubresult(OPERATION_VALIDATE_VALUE);
Class<O> clazz = ObjectTypes.getClassFromRestType(type);
Response response = null;
if (policyItemsDefinition == null) {
LOGGER.error("Policy items definition must not be null");
parentResult.recordFatalError("Policy items definition must not be null");
ResponseBuilder builder = Response.status(Status.BAD_REQUEST).entity(parentResult);
return builder.build();
}
try {
PrismObject<O> object = model.getObject(clazz, oid, null, task, parentResult);
PrismObject<ValuePolicyType> valuePolicy = resolvePolicy(object, task, parentResult);
for (PolicyItemDefinitionType policyItemDefinition : policyItemsDefinition
.getPolicyItemDefinition()) {
validateValue(object, valuePolicy, policyItemDefinition, task, parentResult);
}
parentResult.computeStatusIfUnknown();;
ResponseBuilder responseBuilder = null;
if (parentResult.isAcceptable()) {
responseBuilder = Response.ok();
} else {
responseBuilder = Response.status(Status.CONFLICT).entity(parentResult);
}
response = responseBuilder.build();
} catch (Exception ex) {
parentResult.computeStatus();
response = RestServiceUtil.handleException(parentResult, ex);
}
finishRequest(task);
return response;
}
private <T, O extends ObjectType> boolean validateValue(PrismObject<O> object, PrismObject<ValuePolicyType> policy, PolicyItemDefinitionType policyItemDefinition, Task task, OperationResult parentResult) throws ExpressionEvaluationException, SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException, SecurityViolationException, PolicyViolationException {
ValuePolicyType stringPolicy = null;
if (policyItemDefinition.getValuePolicyRef() != null) {
PrismObject<ValuePolicyType> valuePolicy = model.getObject(ValuePolicyType.class, policyItemDefinition.getValuePolicyRef().getOid(), null, task, parentResult);
PrismObject<ValuePolicyType> policyOverride = valuePolicy.clone();
stringPolicy = policyOverride != null ? policyOverride.asObjectable() : null;
} else {
if (policy == null) {
SystemConfigurationType systemConfiguration = modelInteraction
.getSystemConfiguration(parentResult);
if (systemConfiguration.getGlobalPasswordPolicyRef() != null) {
PrismObject<ValuePolicyType> valuePolicy = model.getObject(ValuePolicyType.class,
systemConfiguration.getGlobalPasswordPolicyRef().getOid(), null, task,
parentResult);
stringPolicy = valuePolicy != null ? valuePolicy.asObjectable() : null;
}
} else {
stringPolicy = policy != null ? policy.asObjectable() : null;
}
}
RawType rawValue = (RawType) policyItemDefinition.getValue();
String valueToValidate = null;
List<String> valuesToValidate = new ArrayList<>();
PolicyItemTargetType target = policyItemDefinition.getTarget();
ItemPath path = null;
if (target != null) {
path = target.getPath().getItemPath();
}
if (rawValue != null) {
valueToValidate = rawValue.getParsedRealValue(String.class);
valuesToValidate.add(valueToValidate);
} else {
if (target == null || target.getPath() == null) {
LOGGER.error("Target item path must be defined");
parentResult.recordFatalError("Target item path must be defined");
throw new SchemaException("Target item path must be defined");
}
path = target.getPath().getItemPath();
PrismProperty<T> property = object.findProperty(path);
if (property == null || property.isEmpty()) {
LOGGER.error("Attribute {} has no value. Nothing to validate.", property);
parentResult.recordFatalError("Attribute " + property + " has no value. Nothing to validate");
throw new SchemaException("Attribute " + property + " has no value. Nothing to validate");
}
PrismPropertyDefinition<T> itemToValidateDefinition = property.getDefinition();
QName definitionName = itemToValidateDefinition.getTypeName();
if (!QNameUtil.qNameToUri(definitionName).equals(QNameUtil.qNameToUri(DOMUtil.XSD_STRING))
&& !QNameUtil.qNameToUri(definitionName).equals(QNameUtil.qNameToUri(PolyStringType.COMPLEX_TYPE))
&& !QNameUtil.qNameToUri(definitionName).equals(QNameUtil.qNameToUri(ProtectedStringType.COMPLEX_TYPE))) {
LOGGER.error("Trying to validate string policy on the property of type {} failed. Unsupported type.",
itemToValidateDefinition);
parentResult.recordFatalError("Trying to validate string policy on the property of type "
+ itemToValidateDefinition + " failed. Unsupported type.");
throw new SchemaException("Trying to validate string policy on the property of type "
+ itemToValidateDefinition + " failed. Unsupported type.");
}
if (itemToValidateDefinition.isSingleValue()) {
if (definitionName.equals(PolyStringType.COMPLEX_TYPE)) {
valueToValidate = ((PolyString) property.getRealValue()).getOrig();
} else if (definitionName.equals(ProtectedStringType.COMPLEX_TYPE)){
ProtectedStringType protectedString = ((ProtectedStringType) property.getRealValue());
valueToValidate = getClearValue(protectedString);
} else {
valueToValidate = (String) property.getRealValue();
}
valuesToValidate.add(valueToValidate);
} else {
if (definitionName.equals(DOMUtil.XSD_STRING)) {
valuesToValidate.addAll(property.getRealValues(String.class));
} else if (definitionName.equals(ProtectedStringType.COMPLEX_TYPE)) {
for (ProtectedStringType protectedString : property.getRealValues(ProtectedStringType.class)) {
valuesToValidate.add(getClearValue(protectedString));
}
} else {
for (PolyString val : property.getRealValues(PolyString.class)) {
valuesToValidate.add(val.getOrig());
}
}
}
}
for (String newValue : valuesToValidate) {
OperationResult result = parentResult.createSubresult(OPERATION_VALIDATE_VALUE + ".value");
if (path != null ) result.addParam("path", path);
result.addParam("valueToValidate", newValue);
if (!policyProcessor.validateValue(newValue, stringPolicy, object, "validate value " + path!= null ? "for " + path : "" + " for " + object + " value " + valueToValidate, task, result)) {
result.recordFatalError("Validation for value " + newValue + " against policy " + stringPolicy + " failed");
LOGGER.error("Validation for value {} against policy {} failed", newValue, stringPolicy);
}
result.computeStatusIfUnknown();
}
parentResult.computeStatusIfUnknown();
return parentResult.isAcceptable();
}
private String getClearValue(ProtectedStringType protectedString) throws SchemaException, PolicyViolationException {
try {
if (protectedString.isEncrypted()) {
return protector.decryptString(protectedString);
} else if (protectedString.getClearValue() != null) {
return protector.decryptString(protectedString);
} else if (protectedString.isHashed()) {
throw new SchemaException("Cannot validate value of hashed password");
}
} catch (EncryptionException e) {
throw new PolicyViolationException(e.getMessage(), e);
}
return null;
}
@GET
@Path("/users/{id}/policy")
public Response getValuePolicyForUser(@PathParam("id") String oid, @Context MessageContext mc) {
LOGGER.debug("getValuePolicyForUser start");
Task task = RestServiceUtil.initRequest(mc);
OperationResult parentResult = task.getResult().createSubresult(OPERATION_GET);
Response response;
try {
Collection<SelectorOptions<GetOperationOptions>> options =
SelectorOptions.createCollection(GetOperationOptions.createRaw());
PrismObject<UserType> user = model.getObject(UserType.class, oid, options, task, parentResult);
CredentialsPolicyType policy = modelInteraction.getCredentialsPolicy(user, task, parentResult);
ResponseBuilder builder = Response.ok();
builder.entity(policy);
response = builder.build();
} catch (Exception ex) {
response = RestServiceUtil.handleException(parentResult, ex);
}
parentResult.computeStatus();
finishRequest(task);
LOGGER.debug("getValuePolicyForUser finish");
return response;
}
@GET
@Path("/{type}/{id}")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, "application/yaml"})
public <T extends ObjectType> Response getObject(@PathParam("type") String type, @PathParam("id") String id,
@QueryParam("options") List<String> options,
@QueryParam("include") List<String> include,
@QueryParam("exclude") List<String> exclude,
@Context MessageContext mc){
LOGGER.debug("model rest service for get operation start");
Task task = RestServiceUtil.initRequest(mc);
OperationResult parentResult = task.getResult().createSubresult(OPERATION_GET);
Class<T> clazz = ObjectTypes.getClassFromRestType(type);
Collection<SelectorOptions<GetOperationOptions>> getOptions = GetOperationOptions.fromRestOptions(options, include, exclude);
Response response;
try {
PrismObject<T> object;
if (NodeType.class.equals(clazz) && CURRENT.equals(id)) {
String nodeId = taskManager.getNodeId();
ObjectQuery query = QueryBuilder.queryFor(NodeType.class, prismContext)
.item(NodeType.F_NODE_IDENTIFIER).eq(nodeId)
.build();
List<PrismObject<NodeType>> objects = model.searchObjects(NodeType.class, query, getOptions, task, parentResult);
if (objects.isEmpty()) {
throw new ObjectNotFoundException("Current node (id " + nodeId + ") couldn't be found.");
} else if (objects.size() > 1) {
throw new IllegalStateException("More than one 'current' node (id " + nodeId + ") found.");
} else {
object = (PrismObject<T>) objects.get(0);
}
} else {
object = model.getObject(clazz, id, getOptions, task, parentResult);
}
removeExcludes(object, exclude); // temporary measure until fixed in repo
ResponseBuilder builder = Response.ok();
builder.entity(object);
response = builder.build();
} catch (Exception ex) {
response = RestServiceUtil.handleException(parentResult, ex);
}
parentResult.computeStatus();
finishRequest(task);
return response;
}
@GET
@Path("/self")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, "application/yaml"})
public <T extends ObjectType> Response getSelf(@Context MessageContext mc){
LOGGER.debug("model rest service for get operation start");
Task task = RestServiceUtil.initRequest(mc);
OperationResult parentResult = task.getResult().createSubresult(OPERATION_SELF);
Response response;
try {
UserType user = SecurityUtil.getPrincipal().getUser();
ResponseBuilder builder = Response.ok();
builder.entity(user.asPrismObject());
response = builder.build();
parentResult.recordSuccessIfUnknown();
} catch (SecurityViolationException e) {
response = RestServiceUtil.handleException(parentResult, e);
}
finishRequest(task);
return response;
}
@POST
@Path("/{type}")
@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, "application/yaml"})
public <T extends ObjectType> Response addObject(@PathParam("type") String type, PrismObject<T> object,
@QueryParam("options") List<String> options,
@Context UriInfo uriInfo, @Context MessageContext mc) {
LOGGER.debug("model rest service for add operation start");
Task task = RestServiceUtil.initRequest(mc);
OperationResult parentResult = task.getResult().createSubresult(OPERATION_ADD_OBJECT);
Class clazz = ObjectTypes.getClassFromRestType(type);
if (!object.getCompileTimeClass().equals(clazz)){
finishRequest(task);
parentResult.recordFatalError("Request to add object of type "
+ object.getCompileTimeClass().getSimpleName() + " to the collection of " + type);
return RestServiceUtil.createErrorResponseBuilder(Status.BAD_REQUEST, parentResult).build();
}
ModelExecuteOptions modelExecuteOptions = ModelExecuteOptions.fromRestOptions(options);
String oid;
Response response;
try {
oid = model.addObject(object, modelExecuteOptions, task, parentResult);
LOGGER.debug("returned oid : {}", oid );
ResponseBuilder builder;
if (oid != null) {
URI resourceURI = uriInfo.getAbsolutePathBuilder().path(oid).build(oid);
builder = clazz.isAssignableFrom(TaskType.class) ? // TODO not the other way around?
Response.accepted().location(resourceURI) : Response.created(resourceURI);
} else {
// OID might be null e.g. if the object creation is a subject of workflow approval
builder = Response.accepted(); // TODO is this ok ?
}
// (not used currently)
//validateIfRequested(object, options, builder, task, parentResult);
response = builder.build();
} catch (Exception ex) {
response = RestServiceUtil.handleException(parentResult, ex);
}
parentResult.computeStatus();
finishRequest(task);
return response;
}
@GET
@Path("/{type}")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, "application/yaml"})
public <T extends ObjectType> Response searchObjectsByType(@PathParam("type") String type, @QueryParam("options") List<String> options,
@Context UriInfo uriInfo, @Context MessageContext mc) {
Task task = RestServiceUtil.initRequest(mc);
OperationResult parentResult = task.getResult().createSubresult(OPERATION_SEARCH_OBJECTS);
Class<T> clazz = ObjectTypes.getClassFromRestType(type);
Response response;
try {
Collection<SelectorOptions<GetOperationOptions>> searchOptions = GetOperationOptions.fromRestOptions(options, null, null);
List<PrismObject<T>> objects = model.searchObjects(clazz, null, searchOptions, task, parentResult);
ObjectListType listType = new ObjectListType();
if (objects != null){
List<ObjectType> list = objects.stream().map(o -> convert(clazz, o, parentResult.createOperationResultType())).collect(Collectors.toList());
listType.getObject().addAll(list);
}
response = Response.ok().entity(listType).build();
} catch (Exception ex) {
response = RestServiceUtil.handleException(parentResult, ex);
}
parentResult.computeStatus();
finishRequest(task);
return response;
}
private ObjectType convert(Class clazz, PrismObject<? extends ObjectType> o, OperationResultType result) {
ObjectType objType = null;
try {
objType = (ObjectType) prismContext.getSchemaRegistry().findObjectDefinitionByCompileTimeClass(clazz).instantiate().asObjectable();
objType.setOid(o.getOid());
objType.setName(o.asObjectable().getName());
return objType;
} catch (SchemaException e) {
// TODO Auto-generated catch block
return objType;
}
}
// currently unused; but potentially useful in future
private <T extends ObjectType> void validateIfRequested(PrismObject<?> object,
List<String> options, ResponseBuilder builder, Task task,
OperationResult parentResult) {
if (options != null && options.contains(VALIDATE) && object.asObjectable() instanceof ResourceType) {
ValidationResult validationResult = resourceValidator
.validate((PrismObject<ResourceType>) object, Scope.THOROUGH, null, task, parentResult);
builder.entity(validationResult.toValidationResultType()); // TODO move to parentResult, and return the result!
}
}
@PUT
@Path("/{type}/{id}")
@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, "application/yaml"})
public <T extends ObjectType> Response addObject(@PathParam("type") String type, @PathParam("id") String id,
PrismObject<T> object, @QueryParam("options") List<String> options, @Context UriInfo uriInfo,
@Context Request request, @Context MessageContext mc){
LOGGER.debug("model rest service for add operation start");
Task task = RestServiceUtil.initRequest(mc);
OperationResult parentResult = task.getResult().createSubresult(OPERATION_ADD_OBJECT);
Class clazz = ObjectTypes.getClassFromRestType(type);
if (!object.getCompileTimeClass().equals(clazz)){
finishRequest(task);
parentResult.recordFatalError("Request to add object of type "
+ object.getCompileTimeClass().getSimpleName()
+ " to the collection of " + type);
return RestServiceUtil.createErrorResponseBuilder(Status.BAD_REQUEST, parentResult).build();
}
ModelExecuteOptions modelExecuteOptions = ModelExecuteOptions.fromRestOptions(options);
if (modelExecuteOptions == null) {
modelExecuteOptions = ModelExecuteOptions.createOverwrite();
} else if (!ModelExecuteOptions.isOverwrite(modelExecuteOptions)){
modelExecuteOptions.setOverwrite(Boolean.TRUE);
}
String oid;
ResponseBuilder builder;
try {
oid = model.addObject(object, modelExecuteOptions, task, parentResult);
LOGGER.debug("returned oid : {}", oid);
URI resourceURI = uriInfo.getAbsolutePathBuilder().path(oid).build(oid);
builder = clazz.isAssignableFrom(TaskType.class) ?
Response.accepted().location(resourceURI) : Response.created(resourceURI);
// (not used currently)
//validateIfRequested(object, options, builder, task, parentResult);
} catch (Exception ex) {
builder = RestServiceUtil.createErrorResponseBuilder(parentResult, ex);
}
parentResult.computeStatus();
Response response = RestServiceUtil.createResultHeaders(builder, parentResult).build();
finishRequest(task);
return response;
}
@DELETE
@Path("/{type}/{id}")
// @Produces({"text/html", "application/xml"})
public Response deleteObject(@PathParam("type") String type, @PathParam("id") String id,
@QueryParam("options") List<String> options, @Context MessageContext mc){
LOGGER.debug("model rest service for delete operation start");
Task task = RestServiceUtil.initRequest(mc);
OperationResult parentResult = task.getResult().createSubresult(OPERATION_DELETE_OBJECT);
Class clazz = ObjectTypes.getClassFromRestType(type);
Response response;
try {
if (clazz.isAssignableFrom(TaskType.class)){
model.suspendAndDeleteTasks(MiscUtil.createCollection(id), WAIT_FOR_TASK_STOP, true, parentResult);
parentResult.computeStatus();
finishRequest(task);
if (parentResult.isSuccess()){
return Response.noContent().build();
}
return Response.serverError().entity(parentResult.getMessage()).build();
}
ModelExecuteOptions modelExecuteOptions = ModelExecuteOptions.fromRestOptions(options);
model.deleteObject(clazz, id, modelExecuteOptions, task, parentResult);
response = Response.noContent().build();
} catch (Exception ex) {
response = RestServiceUtil.handleException(parentResult, ex);
}
parentResult.computeStatus();
finishRequest(task);
return response;
}
@POST
@Path("/{type}/{oid}")
@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, "application/yaml"})
public <T extends ObjectType> Response modifyObjectPost(@PathParam("type") String type, @PathParam("oid") String oid,
ObjectModificationType modificationType, @QueryParam("options") List<String> options, @Context MessageContext mc) {
return modifyObjectPatch(type, oid, modificationType, options, mc);
}
@PATCH
@Path("/{type}/{oid}")
@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, "application/yaml"})
public <T extends ObjectType> Response modifyObjectPatch(@PathParam("type") String type, @PathParam("oid") String oid,
ObjectModificationType modificationType, @QueryParam("options") List<String> options, @Context MessageContext mc) {
LOGGER.debug("model rest service for modify operation start");
Task task = RestServiceUtil.initRequest(mc);
OperationResult parentResult = task.getResult().createSubresult(OPERATION_MODIFY_OBJECT);
Class clazz = ObjectTypes.getClassFromRestType(type);
Response response;
try {
ModelExecuteOptions modelExecuteOptions = ModelExecuteOptions.fromRestOptions(options);
Collection<? extends ItemDelta> modifications = DeltaConvertor.toModifications(modificationType, clazz, prismContext);
model.modifyObject(clazz, oid, modifications, modelExecuteOptions, task, parentResult);
response = Response.noContent().build();
} catch (Exception ex) {
response = RestServiceUtil.handleException(parentResult, ex);
}
parentResult.computeStatus();
finishRequest(task);
return response;
}
@POST
@Path("/notifyChange")
@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, "application/yaml"})
public Response notifyChange(ResourceObjectShadowChangeDescriptionType changeDescription,
@Context UriInfo uriInfo, @Context MessageContext mc) {
LOGGER.debug("model rest service for notify change operation start");
Validate.notNull(changeDescription, "Chnage description must not be null");
Task task = RestServiceUtil.initRequest(mc);
OperationResult parentResult = task.getResult().createSubresult(OPERATION_NOTIFY_CHANGE);
Response response;
try {
model.notifyChange(changeDescription, parentResult, task);
return Response.ok().build();
// String oldShadowOid = changeDescription.getOldShadowOid();
// if (oldShadowOid != null){
// URI resourceURI = uriInfo.getAbsolutePathBuilder().path(oldShadowOid).build(oldShadowOid);
// return Response.accepted().location(resourceURI).build();
// } else {
// changeDescription.get
// }
// response = Response.seeOther((uriInfo.getBaseUriBuilder().path(this.getClass(), "getObject").build(ObjectTypes.TASK.getRestType(), task.getOid()))).build();
} catch (Exception ex) {
response = RestServiceUtil.handleException(parentResult, ex);
}
parentResult.computeStatus();
finishRequest(task);
return response;
}
@GET
@Path("/shadows/{oid}/owner")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, "application/yaml"})
public Response findShadowOwner(@PathParam("oid") String shadowOid, @Context MessageContext mc){
Task task = RestServiceUtil.initRequest(mc);
OperationResult parentResult = task.getResult().createSubresult(OPERATION_FIND_SHADOW_OWNER);
Response response;
try {
PrismObject<UserType> user = model.findShadowOwner(shadowOid, task, parentResult);
response = Response.ok().entity(user).build();
} catch (Exception ex) {
response = RestServiceUtil.handleException(parentResult, ex);
}
parentResult.computeStatus();
finishRequest(task);
return response;
}
@POST
@Path("/{type}/search")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, "application/yaml"})
@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, "application/yaml"})
public Response searchObjects(@PathParam("type") String type, QueryType queryType,
@QueryParam("options") List<String> options,
@QueryParam("include") List<String> include,
@QueryParam("exclude") List<String> exclude,
@Context MessageContext mc){
Task task = RestServiceUtil.initRequest(mc);
OperationResult parentResult = task.getResult().createSubresult(OPERATION_SEARCH_OBJECTS);
Class clazz = ObjectTypes.getClassFromRestType(type);
Response response;
try {
ObjectQuery query = QueryJaxbConvertor.createObjectQuery(clazz, queryType, prismContext);
Collection<SelectorOptions<GetOperationOptions>> searchOptions = GetOperationOptions.fromRestOptions(options, include, exclude);
List<PrismObject<? extends ObjectType>> objects = model.searchObjects(clazz, query, searchOptions, task, parentResult);
ObjectListType listType = new ObjectListType();
for (PrismObject<? extends ObjectType> o : objects) {
removeExcludes(o, exclude); // temporary measure until fixed in repo
listType.getObject().add(o.asObjectable());
}
response = Response.ok().entity(listType).build();
} catch (Exception ex) {
response = RestServiceUtil.handleException(parentResult, ex);
}
parentResult.computeStatus();
finishRequest(task);
return response;
}
private void removeExcludes(PrismObject<? extends ObjectType> object, List<String> exclude) {
for (ItemPath path : ItemPath.fromStringList(exclude)) {
Item item = object.findItem(path); // reduce to "removeItem" after fixing that method implementation
if (item != null) {
object.removeItem(item.getPath(), Item.class);
}
}
}
@POST
@Path("/resources/{resourceOid}/import/{objectClass}")
@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, "application/yaml"})
public Response importFromResource(@PathParam("resourceOid") String resourceOid, @PathParam("objectClass") String objectClass,
@Context MessageContext mc, @Context UriInfo uriInfo) {
LOGGER.debug("model rest service for import from resource operation start");
Task task = RestServiceUtil.initRequest(mc);
OperationResult parentResult = task.getResult().createSubresult(OPERATION_IMPORT_FROM_RESOURCE);
QName objClass = new QName(MidPointConstants.NS_RI, objectClass);
Response response;
try {
model.importFromResource(resourceOid, objClass, task, parentResult);
response = Response.seeOther((uriInfo.getBaseUriBuilder().path(this.getClass(), "getObject")
.build(ObjectTypes.TASK.getRestType(), task.getOid()))).build();
} catch (Exception ex) {
response = RestServiceUtil.handleException(parentResult, ex);
}
parentResult.computeStatus();
finishRequest(task);
return response;
}
@POST
@Path("/resources/{resourceOid}/test")
// @Produces({"text/html", "application/xml"})
public Response testResource(@PathParam("resourceOid") String resourceOid, @Context MessageContext mc) {
LOGGER.debug("model rest service for test resource operation start");
Task task = RestServiceUtil.initRequest(mc);
OperationResult parentResult = task.getResult().createSubresult(OPERATION_TEST_RESOURCE);
Response response;
OperationResult testResult = null;
try {
testResult = model.testResource(resourceOid, task);
response = Response.ok(testResult).build();
} catch (Exception ex) {
response = RestServiceUtil.handleException(parentResult, ex);
}
if (testResult != null) {
parentResult.getSubresults().add(testResult);
}
finishRequest(task);
return response;
}
@POST
@Path("/tasks/{oid}/suspend")
public Response suspendTasks(@PathParam("oid") String taskOid, @Context MessageContext mc) {
Task task = RestServiceUtil.initRequest(mc);
OperationResult parentResult = task.getResult().createSubresult(OPERATION_SUSPEND_TASKS);
Response response;
Collection<String> taskOids = MiscUtil.createCollection(taskOid);
try {
model.suspendTasks(taskOids, WAIT_FOR_TASK_STOP, parentResult);
parentResult.computeStatus();
if (parentResult.isSuccess()){
response = Response.noContent().build();
} else {
response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(parentResult.getMessage()).build();
}
} catch (Exception ex) {
response = RestServiceUtil.handleException(parentResult, ex);
}
finishRequest(task);
return response;
}
// @DELETE
// @Path("tasks/{oid}/suspend")
public Response suspendAndDeleteTasks(@PathParam("oid") String taskOid, @Context MessageContext mc) {
Task task = RestServiceUtil.initRequest(mc);
OperationResult parentResult = task.getResult().createSubresult(OPERATION_SUSPEND_AND_DELETE_TASKS);
Response response;
Collection<String> taskOids = MiscUtil.createCollection(taskOid);
try {
model.suspendAndDeleteTasks(taskOids, WAIT_FOR_TASK_STOP, true, parentResult);
parentResult.computeStatus();
if (parentResult.isSuccess()) {
response = Response.accepted().build();
} else {
response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(parentResult.getMessage()).build();
}
} catch (Exception ex) {
response = RestServiceUtil.handleException(parentResult, ex);
}
finishRequest(task);
return response;
}
@POST
@Path("/tasks/{oid}/resume")
public Response resumeTasks(@PathParam("oid") String taskOid, @Context MessageContext mc) {
Task task = RestServiceUtil.initRequest(mc);
OperationResult parentResult = task.getResult().createSubresult(OPERATION_RESUME_TASKS);
Response response;
Collection<String> taskOids = MiscUtil.createCollection(taskOid);
try {
model.resumeTasks(taskOids, parentResult);
parentResult.computeStatus();
if (parentResult.isSuccess()) {
response = Response.accepted().build();
} else {
response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(parentResult.getMessage()).build();
}
} catch (Exception ex) {
response = RestServiceUtil.handleException(parentResult, ex);
}
finishRequest(task);
return response;
}
@POST
@Path("tasks/{oid}/run")
public Response scheduleTasksNow(@PathParam("oid") String taskOid, @Context MessageContext mc) {
Task task = RestServiceUtil.initRequest(mc);
OperationResult parentResult = task.getResult().createSubresult(OPERATION_SCHEDULE_TASKS_NOW);
Collection<String> taskOids = MiscUtil.createCollection(taskOid);
Response response;
try {
model.scheduleTasksNow(taskOids, parentResult);
parentResult.computeStatus();
if (parentResult.isSuccess()) {
response = Response.accepted().build();
} else {
response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(parentResult.getMessage()).build();
}
} catch (Exception ex) {
response = RestServiceUtil.handleException(parentResult, ex);
}
finishRequest(task);
return response;
}
@POST
@Path("/rpc/executeScript")
// @Produces({"text/html", "application/xml"})
@Consumes({"application/xml" })
public <T extends ObjectType> Response executeScript(ScriptingExpressionType scriptingExpression,
@QueryParam("asynchronous") Boolean asynchronous,
@Context UriInfo uriInfo, @Context MessageContext mc) {
Task task = RestServiceUtil.initRequest(mc);
OperationResult result = task.getResult().createSubresult(OPERATION_EXECUTE_SCRIPT);
String oid;
Response response;
try {
ResponseBuilder builder;
if (Boolean.TRUE.equals(asynchronous)) {
scriptingService.evaluateExpression(scriptingExpression, task, result);
URI resourceUri = uriInfo.getAbsolutePathBuilder().path(task.getOid()).build(task.getOid());
builder = Response.created(resourceUri);
} else {
ScriptExecutionResult executionResult = scriptingService.evaluateExpression(scriptingExpression, task, result);
ExecuteScriptsResponseType operationOutput = new ExecuteScriptsResponseType();
operationOutput.setResult(result.createOperationResultType());
ScriptOutputsType outputs = new ScriptOutputsType();
operationOutput.setOutputs(outputs);
SingleScriptOutputType output = new SingleScriptOutputType();
output.setTextOutput(executionResult.getConsoleOutput());
output.setXmlData(prepareXmlData(executionResult.getDataOutput()));
outputs.getOutput().add(output);
builder = Response.ok();
builder.entity(operationOutput);
}
response = builder.build();
} catch (Exception ex) {
response = RestServiceUtil.handleException(result, ex);
LoggingUtils.logUnexpectedException(LOGGER, "Couldn't execute script.", ex);
}
result.computeStatus();
finishRequest(task);
return response;
}
private ItemListType prepareXmlData(List<PrismValue> output) throws JAXBException, SchemaException {
ItemListType itemListType = new ItemListType();
if (output != null) {
for (PrismValue value : output) {
RawType rawType = new RawType(prismContext.xnodeSerializer().root(SchemaConstants.C_VALUE).serialize(value), prismContext);
itemListType.getItem().add(rawType);
}
}
return itemListType;
}
@POST
@Path("/rpc/compare")
// @Produces({"text/html", "application/xml"})
@Consumes({"application/xml" })
public <T extends ObjectType> Response compare(PrismObject<T> clientObject,
@QueryParam("readOptions") List<String> restReadOptions,
@QueryParam("compareOptions") List<String> restCompareOptions,
@QueryParam("ignoreItems") List<String> restIgnoreItems,
@Context MessageContext mc) {
Task task = RestServiceUtil.initRequest(mc);
OperationResult result = task.getResult().createSubresult(OPERATION_COMPARE);
Response response;
try {
ResponseBuilder builder;
List<ItemPath> ignoreItemPaths = ItemPath.fromStringList(restIgnoreItems);
final GetOperationOptions getOpOptions = GetOperationOptions.fromRestOptions(restReadOptions);
Collection<SelectorOptions<GetOperationOptions>> readOptions =
getOpOptions != null ? SelectorOptions.createCollection(getOpOptions) : null;
ModelCompareOptions compareOptions = ModelCompareOptions.fromRestOptions(restCompareOptions);
CompareResultType compareResult = modelService.compareObject(clientObject, readOptions, compareOptions, ignoreItemPaths, task, result);
builder = Response.ok();
builder.entity(compareResult);
response = builder.build();
} catch (Exception ex) {
response = RestServiceUtil.handleException(result, ex);
}
result.computeStatus();
finishRequest(task);
return response;
}
@GET
@Path("/log/size")
@Produces({"text/plain"})
public Response getLogFileSize(@Context MessageContext mc) {
Task task = RestServiceUtil.initRequest(mc);
OperationResult result = task.getResult().createSubresult(OPERATION_GET_LOG_FILE_SIZE);
Response response;
try {
long size = modelDiagnosticService.getLogFileSize(task, result);
ResponseBuilder builder = Response.ok();
builder.entity(String.valueOf(size));
response = builder.build();
} catch (Exception ex) {
response = RestServiceUtil.handleException(result, ex);
}
result.computeStatus();
finishRequest(task);
return response;
}
@GET
@Path("/log")
@Produces({"text/plain"})
public Response getLog(@QueryParam("fromPosition") Long fromPosition, @QueryParam("maxSize") Long maxSize, @Context MessageContext mc) {
Task task = RestServiceUtil.initRequest(mc);
OperationResult result = task.getResult().createSubresult(OPERATION_GET_LOG_FILE_CONTENT);
Response response;
try {
LogFileContentType content = modelDiagnosticService.getLogFileContent(fromPosition, maxSize, task, result);
ResponseBuilder builder = Response.ok();
builder.entity(content.getContent());
builder.header("ReturnedDataPosition", content.getAt());
builder.header("ReturnedDataComplete", content.isComplete());
builder.header("CurrentLogFileSize", content.getLogFileSize());
response = builder.build();
} catch (Exception ex) {
LoggingUtils.logUnexpectedException(LOGGER, "Cannot get log file content: fromPosition={}, maxSize={}", ex, fromPosition, maxSize);
response = RestServiceUtil.handleException(result, ex);
}
result.computeStatus();
finishRequest(task);
return response;
}
// @GET
// @Path("tasks/{oid}")
// public Response getTaskByIdentifier(@PathParam("oid") String identifier) throws SchemaException, ObjectNotFoundException {
// OperationResult parentResult = new OperationResult("getTaskByIdentifier");
// PrismObject<TaskType> task = model.getTaskByIdentifier(identifier, null, parentResult);
//
// return Response.ok(task).build();
// }
//
//
// public boolean deactivateServiceThreads(long timeToWait, OperationResult parentResult) {
// return model.deactivateServiceThreads(timeToWait, parentResult);
// }
//
// public void reactivateServiceThreads(OperationResult parentResult) {
// model.reactivateServiceThreads(parentResult);
// }
//
// public boolean getServiceThreadsActivationState() {
// return model.getServiceThreadsActivationState();
// }
//
// public void stopSchedulers(Collection<String> nodeIdentifiers, OperationResult parentResult) {
// model.stopSchedulers(nodeIdentifiers, parentResult);
// }
//
// public boolean stopSchedulersAndTasks(Collection<String> nodeIdentifiers, long waitTime, OperationResult parentResult) {
// return model.stopSchedulersAndTasks(nodeIdentifiers, waitTime, parentResult);
// }
//
// public void startSchedulers(Collection<String> nodeIdentifiers, OperationResult parentResult) {
// model.startSchedulers(nodeIdentifiers, parentResult);
// }
//
// public void synchronizeTasks(OperationResult parentResult) {
// model.synchronizeTasks(parentResult);
// }
private void finishRequest(Task task) {
RestServiceUtil.finishRequest(task, securityHelper);
}
}