package org.ovirt.engine.api.restapi.resource;
import java.text.MessageFormat;
import java.util.List;
import javax.ws.rs.core.Response;
import org.ovirt.engine.api.common.invocation.MetaData;
import org.ovirt.engine.api.common.util.QueryHelper;
import org.ovirt.engine.api.model.Version;
import org.ovirt.engine.api.restapi.util.SessionHelper;
import org.ovirt.engine.core.common.action.LogoutUserParameters;
import org.ovirt.engine.core.common.action.VdcActionParametersBase;
import org.ovirt.engine.core.common.action.VdcActionType;
import org.ovirt.engine.core.common.action.VdcReturnValueBase;
import org.ovirt.engine.core.common.interfaces.SearchType;
import org.ovirt.engine.core.common.queries.ConfigurationValues;
import org.ovirt.engine.core.common.queries.GetConfigurationValueParameters;
import org.ovirt.engine.core.common.queries.SearchParameters;
import org.ovirt.engine.core.common.queries.VdcQueryParametersBase;
import org.ovirt.engine.core.common.queries.VdcQueryReturnValue;
import org.ovirt.engine.core.common.queries.VdcQueryType;
import org.ovirt.engine.core.common.users.VdcUser;
import org.ovirt.engine.core.utils.threadpool.ThreadPoolUtil;
public class BackendResource extends BaseBackendResource {
private static final String ASYNC_CONSTRAINT = "async";
private static final String EXPECT_HEADER = "Expect";
private static final String NON_BLOCKING_EXPECTATION = "202-accepted";
protected <T> T getEntity(Class<T> clz, SearchType searchType, String constraint) {
try {
VdcQueryReturnValue result = backend.RunQuery(VdcQueryType.Search,
sessionize(new SearchParameters(constraint, searchType)));
if (!result.getSucceeded()) {
throw new BackendFailureException(localize(result.getExceptionString()));
}
T entity;
if (List.class.isAssignableFrom(clz) && result.getReturnValue() instanceof List) {
entity = clz.cast(result.getReturnValue());
} else {
List<T> list = asCollection(clz, result.getReturnValue());
if (list == null || list.isEmpty()) {
throw new EntityNotFoundException(constraint);
}
entity = clz.cast(list.get(0));
}
return entity;
} catch (Exception e) {
return handleError(clz, e, false);
}
}
protected <T> T getEntity(Class<T> clz, VdcQueryType query, VdcQueryParametersBase queryParams, String identifier) {
return getEntity(clz, query, queryParams, identifier, false);
}
protected <T> T getEntity(Class<T> clz,
VdcQueryType query,
VdcQueryParametersBase queryParams,
String identifier,
boolean notFoundAs404) {
try {
return doGetEntity(clz, query, queryParams, identifier);
} catch (Exception e) {
return handleError(clz, e, notFoundAs404);
}
}
protected <T> T doGetEntity(Class<T> clz,
VdcQueryType query,
VdcQueryParametersBase queryParams,
String identifier) throws BackendFailureException {
VdcQueryReturnValue result = backend.RunQuery(query, sessionize(queryParams));
if (!result.getSucceeded() || result.getReturnValue() == null) {
if (result.getExceptionString() != null) {
throw new BackendFailureException(localize(result.getExceptionString()));
} else {
throw new EntityNotFoundException(identifier);
}
}
return clz.cast(result.getReturnValue());
}
protected <T> List<T> getBackendCollection(Class<T> clz, VdcQueryType query, VdcQueryParametersBase queryParams) {
try {
VdcQueryReturnValue result = backend.RunQuery(query, sessionize(queryParams));
if (!result.getSucceeded()) {
throw new BackendFailureException(localize(result.getExceptionString()));
}
return asCollection(clz, result.getReturnValue());
} catch (Exception e) {
return handleError(e, false);
}
}
protected Response performAction(VdcActionType task, VdcActionParametersBase params) {
try {
if (QueryHelper.hasMatrixParam(getUriInfo(), ASYNC_CONSTRAINT) ||
expectNonBlocking()) {
getCurrent().get(MetaData.class).set("async", true);
return performNonBlockingAction(task, params);
} else {
doAction(task, params);
return Response.ok().build();
}
} catch (Exception e) {
return handleError(Response.class, e, false);
}
}
protected boolean expectNonBlocking() {
boolean expectNonBlocking = false;
List<String> expect = httpHeaders.getRequestHeader(EXPECT_HEADER);
if (expect != null && expect.size() > 0) {
expectNonBlocking = expect.get(0).equalsIgnoreCase(NON_BLOCKING_EXPECTATION);
}
return expectNonBlocking;
}
protected Response performNonBlockingAction(VdcActionType task, VdcActionParametersBase params) {
try {
doNonBlockingAction(task, params);
return Response.status(Response.Status.ACCEPTED).build();
} catch (Exception e) {
return handleError(Response.class, e, false);
}
}
protected <T> T performAction(VdcActionType task, VdcActionParametersBase params, Class<T> resultType) {
try {
return resultType.cast(doAction(task, params).getActionReturnValue());
} catch (Exception e) {
return handleError(resultType, e, false);
}
}
protected VdcReturnValueBase doAction(VdcActionType task,
VdcActionParametersBase params) throws BackendFailureException {
VdcReturnValueBase result = backend.RunAction(task, sessionize(params));
if (!result.getCanDoAction()) {
throw new BackendFailureException(localize(result.getCanDoActionMessages()));
} else if (!result.getSucceeded()) {
throw new BackendFailureException(localize(result.getExecuteFailedMessages()));
}
assert (result != null);
return result;
}
protected void doNonBlockingAction(final VdcActionType task, final VdcActionParametersBase params) {
ThreadPoolUtil.execute(new Runnable() {
SessionHelper sh = getSessionHelper();
VdcActionParametersBase sp = sessionize(params);
VdcUser user = getCurrent().get(VdcUser.class);
@Override
public void run() {
try {
backend.RunAction(task, sp);
} finally {
if (user != null) {
backend.Logoff(sh.sessionize(new LogoutUserParameters(user.getUserId())));
}
sh.clean();
}
}
});
}
@SuppressWarnings("serial")
protected <T> T getConfigurationValue(Class<T> clz, ConfigurationValues config, final Version version) {
return getEntity(clz,
VdcQueryType.GetConfigurationValue,
new GetConfigurationValueParameters(config){{setVersion(asString(version));}},
config.toString());
}
private static final String VERSION_FORMAT = "{0}.{1}";
private String asString(Version version) {
return version == null ? null : MessageFormat.format(VERSION_FORMAT, version.getMajor(), version.getMinor());
}
}