/*
* Copyright (c) 2010-2013 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.controller;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Collection;
import java.util.List;
import javax.xml.namespace.QName;
import com.evolveum.midpoint.common.configuration.api.MidpointConfiguration;
import com.evolveum.midpoint.model.api.DataModelVisualizer;
import com.evolveum.midpoint.prism.query.builder.QueryBuilder;
import com.evolveum.midpoint.schema.*;
import com.evolveum.midpoint.security.api.AuthorizationConstants;
import com.evolveum.midpoint.security.api.SecurityEnforcer;
import com.evolveum.midpoint.util.exception.*;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import com.evolveum.midpoint.model.api.ModelDiagnosticService;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismObjectDefinition;
import com.evolveum.midpoint.prism.PrismProperty;
import com.evolveum.midpoint.prism.polystring.PolyString;
import com.evolveum.midpoint.prism.query.ObjectQuery;
import com.evolveum.midpoint.provisioning.api.ProvisioningService;
import com.evolveum.midpoint.repo.api.RepositoryService;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.DebugUtil;
import com.evolveum.midpoint.util.MiscUtil;
import com.evolveum.midpoint.util.RandomString;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.prism.xml.ns._public.types_3.PolyStringType;
/**
* @author semancik
*
*/
@Component
public class ModelDiagController implements ModelDiagnosticService {
public static final String CLASS_NAME_WITH_DOT = ModelDiagController.class.getName() + ".";
private static final String REPOSITORY_SELF_TEST_USER = CLASS_NAME_WITH_DOT + "repositorySelfTest.user";
private static final String REPOSITORY_SELF_TEST_LOOKUP_TABLE = CLASS_NAME_WITH_DOT + "repositorySelfTest.lookupTable";
private static final String EXPORT_DATA_MODEL = CLASS_NAME_WITH_DOT + "exportDataModel";
private static final String NAME_PREFIX = "selftest";
private static final int NAME_RANDOM_LENGTH = 5;
private static final String USER_FULL_NAME = "Grăfula Fèlix Teleke z Tölökö";
private static final String USER_GIVEN_NAME = "Fëľïx";
private static final String USER_FAMILY_NAME = "Ţæĺêké";
private static final String[] USER_ORGANIZATION = {"COMITATVS NOBILITVS HVNGARIÆ", "Salsa Verde ğomorula prïvatûła"};
private static final String[] USER_EMPLOYEE_TYPE = {"Ģŗąfųŀą", "CANTATOR"};
private static final String INSANE_NATIONAL_STRING = "Pørúga ném nå väšȍm apârátula";
private static final Trace LOGGER = TraceManager.getTrace(ModelDiagController.class);
private static final String LOG_FILE_CONFIG_KEY = "logFile";
@Autowired
private DataModelVisualizer dataModelVisualizer;
@Autowired
private PrismContext prismContext;
@Autowired
@Qualifier("repositoryService")
private transient RepositoryService repositoryService;
@Autowired
private ProvisioningService provisioningService;
@Autowired
private SecurityEnforcer securityEnforcer;
@Autowired
private MappingDiagEvaluator mappingDiagEvaluator;
@Autowired
private MidpointConfiguration midpointConfiguration;
private RandomString randomString;
ModelDiagController() {
randomString = new RandomString(NAME_RANDOM_LENGTH, true);
}
/* (non-Javadoc)
* @see com.evolveum.midpoint.model.api.ModelDiagnosticService#getRepositoryDiag(com.evolveum.midpoint.task.api.Task, com.evolveum.midpoint.schema.result.OperationResult)
*/
@Override
public RepositoryDiag getRepositoryDiag(Task task, OperationResult parentResult) {
return repositoryService.getRepositoryDiag();
}
/* (non-Javadoc)
* @see com.evolveum.midpoint.model.api.ModelDiagnosticService#repositorySelfTest(com.evolveum.midpoint.task.api.Task)
*/
@Override
public OperationResult repositorySelfTest(Task task) {
OperationResult testResult = new OperationResult(REPOSITORY_SELF_TEST);
// Give repository chance to run its own self-test if available
repositoryService.repositorySelfTest(testResult);
repositorySelfTestUser(task, testResult);
repositorySelfTestLookupTable(task, testResult);
testResult.computeStatus();
return testResult;
}
@Override
public void repositoryTestOrgClosureConsistency(Task task, boolean repairIfNecessary, OperationResult parentResult) throws SchemaException, SecurityViolationException {
OperationResult result = parentResult.createSubresult(REPOSITORY_TEST_ORG_CLOSURE_CONSISTENCY);
try {
securityEnforcer.authorize(AuthorizationConstants.AUTZ_ALL_URL, null, null, null, null, null, result); // only admin can do this
repositoryService.testOrgClosureConsistency(repairIfNecessary, result);
} catch (Throwable t) {
result.recordFatalError(t);
throw t;
} finally {
result.computeStatusIfUnknown();
}
}
@Override
public RepositoryQueryDiagResponse executeRepositoryQuery(RepositoryQueryDiagRequest request, Task task, OperationResult parentResult) throws SchemaException, SecurityViolationException {
OperationResult result = parentResult.createSubresult(EXECUTE_REPOSITORY_QUERY);
try {
boolean isAdmin;
if (request.getImplementationLevelQuery() == null && request.isTranslateOnly()) {
// special case - no hibernate query and translate-only: does not require authorization
isAdmin = false;
} else {
// otherwise admin authorization is required
securityEnforcer.authorize(AuthorizationConstants.AUTZ_ALL_URL, null, null, null, null, null, result);
isAdmin = true;
}
RepositoryQueryDiagResponse response = repositoryService.executeQueryDiagnostics(request, result);
if (!isAdmin && response.getQueryResult() != null) {
// double check we don't leak any data
throw new IllegalStateException("Unauthorized access yields returning data from the repository");
}
return response;
} catch (Throwable t) {
result.recordFatalError(t);
throw t;
} finally {
result.computeStatusIfUnknown();
}
}
@Override
public MappingEvaluationResponseType evaluateMapping(MappingEvaluationRequestType request, Task task,
OperationResult parentResult)
throws SchemaException, SecurityViolationException, ExpressionEvaluationException,
ObjectNotFoundException {
OperationResult result = parentResult.createSubresult(EXECUTE_REPOSITORY_QUERY);
try {
securityEnforcer.authorize(AuthorizationConstants.AUTZ_ALL_URL, null, null, null, null, null, result);
return mappingDiagEvaluator.evaluateMapping(request, task, result);
} catch (Throwable t) {
result.recordFatalError(t);
throw t;
} finally {
result.computeStatusIfUnknown();
}
}
@Override
public OperationResult provisioningSelfTest(Task task) {
OperationResult testResult = new OperationResult(PROVISIONING_SELF_TEST);
// Give provisioning chance to run its own self-test
provisioningService.provisioningSelfTest(testResult, task);
testResult.computeStatus();
return testResult;
}
@Override
public ProvisioningDiag getProvisioningDiag(Task task, OperationResult parentResult) {
return provisioningService.getProvisioningDiag();
}
private void repositorySelfTestUser(Task task, OperationResult testResult) {
OperationResult result = testResult.createSubresult(REPOSITORY_SELF_TEST_USER);
PrismObject<UserType> user;
try {
user = getObjectDefinition(UserType.class).instantiate();
} catch (SchemaException e) {
result.recordFatalError(e);
return;
}
UserType userType = user.asObjectable();
String name = generateRandomName();
PolyStringType namePolyStringType = toPolyStringType(name);
userType.setName(namePolyStringType);
result.addContext("name", name);
userType.setDescription(SelfTestData.POLICIJA);
userType.setFullName(toPolyStringType(USER_FULL_NAME));
userType.setGivenName(toPolyStringType(USER_GIVEN_NAME));
userType.setFamilyName(toPolyStringType(USER_FAMILY_NAME));
userType.setTitle(toPolyStringType(INSANE_NATIONAL_STRING));
userType.getEmployeeType().add(USER_EMPLOYEE_TYPE[0]);
userType.getEmployeeType().add(USER_EMPLOYEE_TYPE[1]);
userType.getOrganization().add(toPolyStringType(USER_ORGANIZATION[0]));
userType.getOrganization().add(toPolyStringType(USER_ORGANIZATION[1]));
String oid;
try {
oid = repositoryService.addObject(user, null, result);
} catch (ObjectAlreadyExistsException | SchemaException | RuntimeException e) {
result.recordFatalError(e);
return;
}
try {
{
OperationResult subresult = result.createSubresult(result.getOperation()+".getObject");
PrismObject<UserType> userRetrieved;
try {
userRetrieved = repositoryService.getObject(UserType.class, oid, null, subresult);
} catch (ObjectNotFoundException | SchemaException | RuntimeException e) {
result.recordFatalError(e);
return;
}
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Self-test:user getObject:\n{}", userRetrieved.debugDump());
}
checkUser(userRetrieved, name, subresult);
subresult.recordSuccessIfUnknown();
}
{
OperationResult subresult = result.createSubresult(result.getOperation()+".searchObjects.fullName");
try {
ObjectQuery query = QueryBuilder.queryFor(UserType.class, prismContext)
.item(UserType.F_FULL_NAME).eq(toPolyString(USER_FULL_NAME))
.build();
subresult.addParam("query", query);
List<PrismObject<UserType>> foundObjects = repositoryService.searchObjects(UserType.class, query , null, subresult);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Self-test:user searchObjects:\n{}", DebugUtil.debugDump(foundObjects));
}
assertSingleSearchResult("user", foundObjects, subresult);
PrismObject<UserType> userRetrieved = foundObjects.iterator().next();
checkUser(userRetrieved, name, subresult);
subresult.recordSuccessIfUnknown();
} catch (SchemaException | RuntimeException e) {
subresult.recordFatalError(e);
return;
}
}
// MID-1116
{
OperationResult subresult = result.createSubresult(result.getOperation()+".searchObjects.employeeType");
try {
ObjectQuery query = QueryBuilder.queryFor(UserType.class, prismContext)
.item(UserType.F_EMPLOYEE_TYPE).eq(USER_EMPLOYEE_TYPE[0])
.build();
subresult.addParam("query", query);
List<PrismObject<UserType>> foundObjects = repositoryService.searchObjects(UserType.class, query , null, subresult);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Self-test:user searchObjects:\n{}", DebugUtil.debugDump(foundObjects));
}
assertSingleSearchResult("user", foundObjects, subresult);
PrismObject<UserType> userRetrieved = foundObjects.iterator().next();
checkUser(userRetrieved, name, subresult);
subresult.recordSuccessIfUnknown();
} catch (SchemaException | RuntimeException e) {
subresult.recordFatalError(e);
return;
}
}
// MID-1116
{
OperationResult subresult = result.createSubresult(result.getOperation()+".searchObjects.organization");
try {
ObjectQuery query = QueryBuilder.queryFor(UserType.class, prismContext)
.item(UserType.F_ORGANIZATION).eq(toPolyString(USER_ORGANIZATION[1]))
.build();
subresult.addParam("query", query);
List<PrismObject<UserType>> foundObjects = repositoryService.searchObjects(UserType.class, query, null, subresult);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Self-test:user searchObjects:\n{}", DebugUtil.debugDump(foundObjects));
}
assertSingleSearchResult("user", foundObjects, subresult);
PrismObject<UserType> userRetrieved = foundObjects.iterator().next();
checkUser(userRetrieved, name, subresult);
subresult.recordSuccessIfUnknown();
} catch (SchemaException | RuntimeException e) {
subresult.recordFatalError(e);
return;
}
}
} finally {
try {
repositoryService.deleteObject(UserType.class, oid, testResult);
} catch (ObjectNotFoundException | RuntimeException e) {
result.recordFatalError(e);
return;
}
result.computeStatus();
}
}
private void checkUser(PrismObject<UserType> userRetrieved, String name, OperationResult subresult) {
checkObjectPropertyPolyString(userRetrieved, UserType.F_NAME, subresult, name);
checkObjectProperty(userRetrieved, UserType.F_DESCRIPTION, subresult, SelfTestData.POLICIJA);
checkObjectPropertyPolyString(userRetrieved, UserType.F_FULL_NAME, subresult, USER_FULL_NAME);
checkObjectPropertyPolyString(userRetrieved, UserType.F_GIVEN_NAME, subresult, USER_GIVEN_NAME);
checkObjectPropertyPolyString(userRetrieved, UserType.F_FAMILY_NAME, subresult, USER_FAMILY_NAME);
checkObjectPropertyPolyString(userRetrieved, UserType.F_TITLE, subresult, INSANE_NATIONAL_STRING);
checkObjectProperty(userRetrieved, UserType.F_EMPLOYEE_TYPE, subresult, USER_EMPLOYEE_TYPE);
checkObjectPropertyPolyString(userRetrieved, UserType.F_ORGANIZATION, subresult, USER_ORGANIZATION);
}
private void repositorySelfTestLookupTable(Task task, OperationResult testResult) {
OperationResult result = testResult.createSubresult(REPOSITORY_SELF_TEST_LOOKUP_TABLE);
PrismObject<LookupTableType> lookupTable;
try {
lookupTable = getObjectDefinition(LookupTableType.class).instantiate();
} catch (SchemaException e) {
result.recordFatalError(e);
return;
}
LookupTableType lookupTableType = lookupTable.asObjectable();
String name = generateRandomName();
PolyStringType namePolyStringType = toPolyStringType(name);
lookupTableType.setName(namePolyStringType);
result.addContext("name", name);
lookupTableType.setDescription(SelfTestData.POLICIJA);
LookupTableRowType rowType = new LookupTableRowType(prismContext);
rowType.setKey(INSANE_NATIONAL_STRING);
rowType.setValue(INSANE_NATIONAL_STRING);
rowType.setLabel(toPolyStringType(INSANE_NATIONAL_STRING));
lookupTableType.getRow().add(rowType);
String oid;
try {
oid = repositoryService.addObject(lookupTable, null, result);
} catch (ObjectAlreadyExistsException | SchemaException | RuntimeException e) {
result.recordFatalError(e);
return;
}
try {
{
OperationResult subresult = result.createSubresult(result.getOperation()+".getObject");
PrismObject<LookupTableType> lookupTableRetrieved;
try {
Collection<SelectorOptions<GetOperationOptions>> options = SelectorOptions.createCollection(LookupTableType.F_ROW,
GetOperationOptions.createRetrieve());
lookupTableRetrieved = repositoryService.getObject(LookupTableType.class, oid, options, subresult);
} catch (ObjectNotFoundException | SchemaException | RuntimeException e) {
result.recordFatalError(e);
return;
}
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Self-test:lookupTable getObject:\n{}", lookupTableRetrieved.debugDump());
}
checkLookupTable(lookupTableRetrieved, name, subresult);
subresult.recordSuccessIfUnknown();
}
{
OperationResult subresult = result.createSubresult(result.getOperation()+".getObject.key");
try {
RelationalValueSearchQuery subquery = new RelationalValueSearchQuery(LookupTableRowType.F_KEY, INSANE_NATIONAL_STRING, RelationalValueSearchType.EXACT);
Collection<SelectorOptions<GetOperationOptions>> options = SelectorOptions.createCollection(LookupTableType.F_ROW,
GetOperationOptions.createRetrieve(subquery));
PrismObject<LookupTableType> lookupTableRetrieved = repositoryService.getObject(LookupTableType.class, oid, options, result);
subresult.addParam("subquery", subquery);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Self-test:lookupTable getObject by row key:\n{}", DebugUtil.debugDump(lookupTableRetrieved));
}
checkLookupTable(lookupTableRetrieved, name, subresult);
subresult.recordSuccessIfUnknown();
} catch (ObjectNotFoundException | SchemaException | RuntimeException e) {
subresult.recordFatalError(e);
return;
}
}
} finally {
try {
repositoryService.deleteObject(LookupTableType.class, oid, testResult);
} catch (ObjectNotFoundException | RuntimeException e) {
result.recordFatalError(e);
return;
}
result.computeStatus();
}
}
private void checkLookupTable(PrismObject<LookupTableType> lookupTable, String name, OperationResult subresult) {
checkObjectPropertyPolyString(lookupTable, LookupTableType.F_NAME, subresult, name);
checkObjectProperty(lookupTable, LookupTableType.F_DESCRIPTION, subresult, SelfTestData.POLICIJA);
LookupTableType lookupTableType = lookupTable.asObjectable();
assertEquals("Unexpected number of rows", 1, lookupTableType.getRow().size(), subresult);
LookupTableRowType rowType = lookupTableType.getRow().get(0);
assertEquals("Unexpected key value", INSANE_NATIONAL_STRING, rowType.getKey(), subresult);
assertEquals("Unexpected 'value' value", INSANE_NATIONAL_STRING, rowType.getValue(), subresult);
assertPolyStringType("Unexpected label value", INSANE_NATIONAL_STRING, rowType.getLabel(), subresult);
}
private void assertSingleSearchResult(String objectTypeMessage, List<PrismObject<UserType>> foundObjects, OperationResult parentResult) {
OperationResult result = parentResult.createSubresult(parentResult.getOperation()+".numberOfResults");
assertTrue("Found no "+objectTypeMessage, !foundObjects.isEmpty(), result);
assertTrue("Expected to find a single "+objectTypeMessage+" but found "+foundObjects.size(), foundObjects.size() == 1, result);
result.recordSuccessIfUnknown();
}
private <O extends ObjectType,T> void checkObjectProperty(PrismObject<O> object, QName propQName, OperationResult parentResult, T... expectedValues) {
String propName = propQName.getLocalPart();
OperationResult result = parentResult.createSubresult(parentResult.getOperation() + ".checkObjectProperty." + propName);
PrismProperty<T> prop = object.findProperty(propQName);
Collection<T> actualValues = prop.getRealValues();
result.addArbitraryCollectionAsParam("actualValues", actualValues);
assertMultivalue("User, property '"+propName+"'", expectedValues, actualValues, result);
result.recordSuccessIfUnknown();
}
private <T> void assertMultivalue(String message, T expectedVals[], Collection<T> actualVals, OperationResult result) {
if (expectedVals.length != actualVals.size()) {
fail(message+": expected "+expectedVals.length+" values but has "+actualVals.size()+" values: "+actualVals, result);
return;
}
for (T expected: expectedVals) {
boolean found = false;
for (T actual: actualVals) {
if (expected.equals(actual)) {
found = true;
break;
}
}
if (!found) {
fail(message+": expected value '"+expected+"' not found in actual values "+actualVals, result);
return;
}
}
}
private <O extends ObjectType> void checkObjectPropertyPolyString(PrismObject<O> object, QName propQName, OperationResult parentResult, String... expectedValues) {
String propName = propQName.getLocalPart();
OperationResult result = parentResult.createSubresult(parentResult.getOperation() + "." + propName);
PrismProperty<PolyString> prop = object.findProperty(propQName);
Collection<PolyString> actualValues = prop.getRealValues();
result.addArbitraryCollectionAsParam("actualValues", actualValues);
assertMultivaluePolyString("User, property '"+propName+"'", expectedValues, actualValues, result);
result.recordSuccessIfUnknown();
}
private void assertMultivaluePolyString(String message, String expectedOrigs[], Collection<PolyString> actualPolyStrings, OperationResult result) {
if (expectedOrigs.length != actualPolyStrings.size()) {
fail(message+": expected "+expectedOrigs.length+" values but has "+actualPolyStrings.size()+" values: "+actualPolyStrings, result);
return;
}
for (String expectedOrig: expectedOrigs) {
boolean found = false;
for (PolyString actualPolyString: actualPolyStrings) {
if (expectedOrig.equals(actualPolyString.getOrig())) {
found = true;
assertEquals(message+ ", norm", polyStringNorm(expectedOrig), actualPolyString.getNorm(), result);
break;
}
}
if (!found) {
fail(message+": expected value '"+expectedOrig+"' not found in actual values "+actualPolyStrings, result);
return;
}
}
}
private void assertPolyString(String message, String expectedOrig, PolyString actualPolyString, OperationResult result) {
assertEquals(message+ ", orig", expectedOrig, actualPolyString.getOrig(), result);
assertEquals(message+ ", norm", polyStringNorm(expectedOrig), actualPolyString.getNorm(), result);
}
private void assertPolyStringType(String message, String expectedName, PolyStringType actualPolyStringType, OperationResult result) {
assertEquals(message+ ", orig", expectedName, actualPolyStringType.getOrig(), result);
assertEquals(message+ ", norm", polyStringNorm(expectedName), actualPolyStringType.getNorm(), result);
}
private String polyStringNorm(String orig) {
return prismContext.getDefaultPolyStringNormalizer().normalize(orig);
}
private void assertTrue(String message, boolean condition, OperationResult result) {
if (!condition) {
fail(message, result);
}
}
private void assertEquals(String message, Object expected, Object actual, OperationResult result) {
if (!MiscUtil.equals(expected, actual)) {
fail(message + "; expected "+expected+", actual "+actual, result);
}
}
private void fail(String message, OperationResult result) {
result.recordFatalError(message);
LOGGER.error("Repository self-test assertion failed: {}", message);
}
private String generateRandomName() {
return NAME_PREFIX + randomString.nextString();
}
private PolyStringType toPolyStringType(String orig) {
PolyStringType polyStringType = new PolyStringType();
polyStringType.setOrig(orig);
return polyStringType;
}
private PolyString toPolyString(String orig) {
PolyString polyString = new PolyString(orig);
polyString.recompute(prismContext.getDefaultPolyStringNormalizer());
return polyString;
}
private <T extends ObjectType> PrismObjectDefinition<T> getObjectDefinition(Class<T> type) {
return prismContext.getSchemaRegistry().findObjectDefinitionByCompileTimeClass(type);
}
@Override
public String exportDataModel(Collection<String> resourceOids,
DataModelVisualizer.Target target, Task task, OperationResult parentResult)
throws SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, SecurityViolationException {
OperationResult result = parentResult.createSubresult(EXPORT_DATA_MODEL);
try {
String rv = dataModelVisualizer.visualize(resourceOids, DataModelVisualizer.Target.DOT, task, result);
result.computeStatusIfUnknown();
return rv;
} catch (Throwable t) {
result.recordFatalError(t.getMessage(), t);
throw t;
}
}
@Override
public String exportDataModel(ResourceType resource, DataModelVisualizer.Target target,
Task task, OperationResult parentResult)
throws SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, SecurityViolationException {
OperationResult result = parentResult.createSubresult(EXPORT_DATA_MODEL);
try {
String rv = dataModelVisualizer.visualize(resource, DataModelVisualizer.Target.DOT, task, result);
result.computeStatusIfUnknown();
return rv;
} catch (Throwable t) {
result.recordFatalError(t.getMessage(), t);
throw t;
}
}
@Override
public LogFileContentType getLogFileContent(Long fromPosition, Long maxSize, Task task, OperationResult parentResult)
throws SecurityViolationException, IOException, SchemaException {
OperationResult result = parentResult.createSubresult(GET_LOG_FILE_CONTENT);
try {
securityEnforcer.authorize(AuthorizationConstants.AUTZ_ALL_URL, null, null, null, null, null, result);
File logFile = getLogFile();
LogFileContentType rv = getLogFileFragment(logFile, fromPosition, maxSize);
result.recordSuccess();
return rv;
} catch (Throwable t) {
result.recordFatalError(t.getMessage(), t);
throw t;
}
}
private LogFileContentType getLogFileFragment(File logFile, Long fromPosition, Long maxSize) throws IOException {
LogFileContentType rv = new LogFileContentType();
RandomAccessFile log = null;
try {
log = new RandomAccessFile(logFile, "r");
long currentLength = log.length();
rv.setLogFileSize(currentLength);
long start;
if (fromPosition == null) {
start = 0;
} else if (fromPosition >= 0) {
start = fromPosition;
} else {
start = Math.max(currentLength + fromPosition, 0);
}
rv.setAt(start);
log.seek(start);
long bytesToRead = Math.max(currentLength - start, 0);
if (maxSize != null && maxSize < bytesToRead) {
bytesToRead = maxSize;
rv.setComplete(false);
} else {
rv.setComplete(true);
}
if (bytesToRead == 0) {
return rv;
} else if (bytesToRead > Integer.MAX_VALUE) {
throw new IllegalStateException("Too many bytes to read from log file: " + bytesToRead);
}
byte[] buffer = new byte[(int) bytesToRead];
log.readFully(buffer);
rv.setContent(new String(buffer));
return rv;
} finally {
if (log != null) {
IOUtils.closeQuietly(log);
}
}
}
@Override
public long getLogFileSize(Task task, OperationResult parentResult) throws SchemaException, SecurityViolationException {
OperationResult result = parentResult.createSubresult(GET_LOG_FILE_SIZE);
try {
securityEnforcer.authorize(AuthorizationConstants.AUTZ_ALL_URL, null, null, null, null, null, result);
File logFile = getLogFile();
long size = logFile.length();
result.recordSuccess();
return size;
} catch (Throwable t) {
result.recordFatalError(t.getMessage(), t);
throw t;
}
}
private File getLogFile() throws SchemaException {
Configuration c = midpointConfiguration.getConfiguration(MidpointConfiguration.SYSTEM_CONFIGURATION_SECTION);
if (c == null || !c.containsKey(LOG_FILE_CONFIG_KEY)) {
throw new SchemaException("No log file specified in system configuration. Please set logFile in <midpoint><system> section.");
}
return new File(c.getString(LOG_FILE_CONFIG_KEY));
}
}