co.cask.cdap.data2.datafabric.dataset.service.executor.DatasetAdminOpHTTPHandler.java Source code

Java tutorial

Introduction

Here is the source code for co.cask.cdap.data2.datafabric.dataset.service.executor.DatasetAdminOpHTTPHandler.java

Source

/*
 * Copyright  2014-2015 Cask Data, Inc.
 *
 * 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 co.cask.cdap.data2.datafabric.dataset.service.executor;

import co.cask.cdap.api.dataset.DatasetAdmin;
import co.cask.cdap.api.dataset.DatasetContext;
import co.cask.cdap.api.dataset.DatasetProperties;
import co.cask.cdap.api.dataset.DatasetSpecification;
import co.cask.cdap.common.HandlerException;
import co.cask.cdap.common.conf.CConfiguration;
import co.cask.cdap.common.conf.Constants;
import co.cask.cdap.data.dataset.SystemDatasetInstantiator;
import co.cask.cdap.data.dataset.SystemDatasetInstantiatorFactory;
import co.cask.cdap.data2.datafabric.dataset.DatasetType;
import co.cask.cdap.data2.datafabric.dataset.RemoteDatasetFramework;
import co.cask.cdap.data2.datafabric.dataset.type.DatasetClassLoaderProvider;
import co.cask.cdap.data2.datafabric.dataset.type.DirectoryClassLoaderProvider;
import co.cask.cdap.data2.dataset2.DatasetManagementException;
import co.cask.cdap.proto.DatasetTypeMeta;
import co.cask.cdap.proto.Id;
import co.cask.http.AbstractHttpHandler;
import co.cask.http.HttpResponder;
import com.google.common.base.Charsets;
import com.google.common.base.Preconditions;
import com.google.gson.Gson;
import com.google.inject.Inject;
import org.apache.commons.lang.StringUtils;
import org.apache.twill.filesystem.LocationFactory;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpResponseStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;

/**
 * Provides REST endpoints for {@link DatasetAdmin} operations.
 */
@Path(Constants.Gateway.API_VERSION_3 + "/namespaces/{namespace-id}")
public class DatasetAdminOpHTTPHandler extends AbstractHttpHandler {

    private static final Logger LOG = LoggerFactory.getLogger(DatasetAdminOpHTTPHandler.class);
    private static final Gson GSON = new Gson();

    private final RemoteDatasetFramework dsFramework;
    private final CConfiguration cConf;
    private final LocationFactory locationFactory;
    private final SystemDatasetInstantiatorFactory datasetInstantiatorFactory;

    @Inject
    public DatasetAdminOpHTTPHandler(RemoteDatasetFramework dsFramework, CConfiguration cConf,
            LocationFactory locationFactory, SystemDatasetInstantiatorFactory datasetInstantiatorFactory) {
        this.dsFramework = dsFramework;
        this.cConf = cConf;
        this.locationFactory = locationFactory;
        this.datasetInstantiatorFactory = datasetInstantiatorFactory;
    }

    @POST
    @Path("/data/datasets/{name}/admin/exists")
    public void exists(HttpRequest request, HttpResponder responder, @PathParam("namespace-id") String namespaceId,
            @PathParam("name") String instanceName) {
        Id.Namespace namespace = Id.Namespace.from(namespaceId);
        try {
            DatasetAdmin datasetAdmin = getDatasetAdmin(Id.DatasetInstance.from(namespace, instanceName));
            responder.sendJson(HttpResponseStatus.OK, new DatasetAdminOpResponse(datasetAdmin.exists(), null));
        } catch (HandlerException e) {
            LOG.debug("Got handler exception", e);
            responder.sendString(e.getFailureStatus(), StringUtils.defaultIfEmpty(e.getMessage(), ""));
        } catch (Exception e) {
            LOG.error(getAdminOpErrorMessage("exists", instanceName), e);
            responder.sendString(HttpResponseStatus.INTERNAL_SERVER_ERROR,
                    getAdminOpErrorMessage("exists", instanceName));
        }
    }

    @POST
    @Path("/data/datasets/{name}/admin/create")
    public void create(HttpRequest request, HttpResponder responder, @PathParam("namespace-id") String namespaceId,
            @PathParam("name") String name) {
        // TODO: Use namespaceId here
        InternalDatasetCreationParams params = GSON.fromJson(request.getContent().toString(Charsets.UTF_8),
                InternalDatasetCreationParams.class);
        Preconditions.checkArgument(params.getProperties() != null, "Missing required 'instanceProps' parameter.");
        Preconditions.checkArgument(params.getTypeMeta() != null, "Missing required 'typeMeta' parameter.");

        DatasetProperties props = params.getProperties();
        DatasetTypeMeta typeMeta = params.getTypeMeta();

        LOG.info("Creating dataset instance {}.{}, type meta: {}, props: {}", namespaceId, name, typeMeta, props);
        try (DatasetClassLoaderProvider classLoaderProvider = new DirectoryClassLoaderProvider(cConf,
                locationFactory)) {
            DatasetType type = dsFramework.getDatasetType(typeMeta, null, classLoaderProvider);

            if (type == null) {
                String msg = String.format("Cannot instantiate dataset type using provided type meta: %s",
                        typeMeta);
                LOG.error(msg);
                responder.sendString(HttpResponseStatus.BAD_REQUEST, msg);
                return;
            }

            DatasetSpecification spec = type.configure(name, props);
            DatasetAdmin admin = type.getAdmin(DatasetContext.from(namespaceId), spec);
            try {
                admin.create();
            } catch (IOException e) {
                responder.sendString(HttpResponseStatus.INTERNAL_SERVER_ERROR,
                        String.format("Error creating dataset \"%s\": %s", name, e.getMessage()));
                return;
            }
            responder.sendJson(HttpResponseStatus.OK, spec);
        } catch (IOException e) {
            LOG.error("Exception instantiating dataset admin for dataset {}", name, e);
            responder.sendString(HttpResponseStatus.INTERNAL_SERVER_ERROR,
                    String.format("Error instantiating the dataset admin for dataset %s", name));
        }
    }

    @POST
    @Path("/data/datasets/{name}/admin/drop")
    public void drop(HttpRequest request, HttpResponder responder, @PathParam("namespace-id") String namespaceId,
            @PathParam("name") String instanceName) throws Exception {

        InternalDatasetDropParams params = GSON.fromJson(request.getContent().toString(Charsets.UTF_8),
                InternalDatasetDropParams.class);
        Preconditions.checkArgument(params.getInstanceSpec() != null, "Missing required 'instanceSpec' parameter.");
        Preconditions.checkArgument(params.getTypeMeta() != null, "Missing required 'typeMeta' parameter.");

        DatasetSpecification spec = params.getInstanceSpec();
        DatasetTypeMeta typeMeta = params.getTypeMeta();

        LOG.info("Dropping dataset with spec: {}, type meta: {}", spec, typeMeta);
        try (DatasetClassLoaderProvider classLoaderProvider = new DirectoryClassLoaderProvider(cConf,
                locationFactory)) {
            DatasetType type = dsFramework.getDatasetType(typeMeta, null, classLoaderProvider);

            if (type == null) {
                String msg = String.format("Cannot instantiate dataset type using provided type meta: %s",
                        typeMeta);
                LOG.error(msg);
                responder.sendString(HttpResponseStatus.BAD_REQUEST, msg);
                return;
            }

            DatasetAdmin admin = type.getAdmin(DatasetContext.from(namespaceId), spec);
            admin.drop();
            responder.sendJson(HttpResponseStatus.OK, spec);
        }
    }

    @POST
    @Path("/data/datasets/{name}/admin/truncate")
    public void truncate(HttpRequest request, HttpResponder responder,
            @PathParam("namespace-id") String namespaceId, @PathParam("name") String instanceName) {
        Id.Namespace namespace = Id.Namespace.from(namespaceId);
        try {
            DatasetAdmin datasetAdmin = getDatasetAdmin(Id.DatasetInstance.from(namespace, instanceName));
            datasetAdmin.truncate();
            responder.sendJson(HttpResponseStatus.OK, new DatasetAdminOpResponse(null, null));
        } catch (HandlerException e) {
            LOG.debug("Got handler exception", e);
            responder.sendString(e.getFailureStatus(), StringUtils.defaultIfEmpty(e.getMessage(), ""));
        } catch (Exception e) {
            LOG.error(getAdminOpErrorMessage("truncate", instanceName), e);
            responder.sendString(HttpResponseStatus.INTERNAL_SERVER_ERROR,
                    getAdminOpErrorMessage("truncate", instanceName));
        }
    }

    @POST
    @Path("/data/datasets/{name}/admin/upgrade")
    public void upgrade(HttpRequest request, HttpResponder responder, @PathParam("namespace-id") String namespaceId,
            @PathParam("name") String instanceName) {
        Id.Namespace namespace = Id.Namespace.from(namespaceId);
        try {
            DatasetAdmin datasetAdmin = getDatasetAdmin(Id.DatasetInstance.from(namespace, instanceName));
            datasetAdmin.upgrade();
            responder.sendJson(HttpResponseStatus.OK, new DatasetAdminOpResponse(null, null));
        } catch (HandlerException e) {
            LOG.debug("Got handler exception", e);
            responder.sendString(e.getFailureStatus(), StringUtils.defaultIfEmpty(e.getMessage(), ""));
        } catch (Exception e) {
            LOG.error(getAdminOpErrorMessage("upgrade", instanceName), e);
            responder.sendString(HttpResponseStatus.INTERNAL_SERVER_ERROR,
                    getAdminOpErrorMessage("upgrade", instanceName));
        }
    }

    private String getAdminOpErrorMessage(String opName, String instanceName) {
        return String.format("Error executing admin operation %s for dataset instance %s", opName, instanceName);
    }

    private DatasetAdmin getDatasetAdmin(Id.DatasetInstance datasetInstanceId)
            throws IOException, DatasetManagementException {

        try (SystemDatasetInstantiator datasetInstantiator = datasetInstantiatorFactory.create()) {
            DatasetAdmin admin = datasetInstantiator.getDatasetAdmin(datasetInstanceId);
            if (admin == null) {
                throw new HandlerException(HttpResponseStatus.NOT_FOUND,
                        "Couldn't obtain DatasetAdmin for dataset instance " + datasetInstanceId);
            }
            return admin;
        }
    }
}