eu.trentorise.opendata.jackan.test.ckan.ExperimentalCkanClient.java Source code

Java tutorial

Introduction

Here is the source code for eu.trentorise.opendata.jackan.test.ckan.ExperimentalCkanClient.java

Source

/*
 * Copyright 2015 Trento Rise.
 *
 * 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 eu.trentorise.opendata.jackan.test.ckan;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import eu.trentorise.opendata.jackan.CheckedCkanClient;
import eu.trentorise.opendata.jackan.CkanClient;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Iterator;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.ByteArrayBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;

/**
 * This client include features that probably... just don't work
 *
 * @author David Leoni
 * @since 0.4.1
 */
class ExperimentalCkanClient extends CkanClient {

    private ExperimentalCkanClient() {
        super();
    }

    public ExperimentalCkanClient(String URL, String token) {
        super(URL, token);
    }

    /**
     * Returns a builder instance. The builder is not threadsafe and you can use
     * one builder instance to build only one client instance.
     */
    public static CkanClient.Builder builder() {
        return CkanClient.newBuilder(new ExperimentalCkanClient());
    }

    /**
     * Uploads a file using file storage api, which I think is deprecated. As of
     * Aug 2015, coesn't work neither with demo.ckan.org nor dati.trentino
     *
     * Adapted from
     * https://github.com/Ontodia/openrefine-ckan-storage-extension/blob/c99de78fd605c4754197668c9396cffd1f9a0267/src/org/deri/orefine/ckan/StorageApiProxy.java#L34
     */
    public String uploadFile(String fileContent, String fileLabel) {
        HttpResponse formFields = null;
        try {
            String filekey = null;
            HttpClient client = new DefaultHttpClient();

            //   get the form fields required from ckan storage
            // notice if you put '3/' it gives not found :-/
            String formUrl = getCatalogUrl() + "/api/storage/auth/form/file/" + fileLabel;
            HttpGet getFormFields = new HttpGet(formUrl);
            getFormFields.setHeader("Authorization", getCkanToken());
            formFields = client.execute(getFormFields);
            HttpEntity entity = formFields.getEntity();
            if (entity != null) {
                ByteArrayOutputStream os = new ByteArrayOutputStream();
                entity.writeTo(os);

                //now parse JSON
                //JSONObject obj = new JSONObject(os.toString());
                JsonNode obj = new ObjectMapper().readTree(os.toString());

                //post the file now
                String uploadFileUrl = getCatalogUrl() + obj.get("action").asText();
                HttpPost postFile = new HttpPost(uploadFileUrl);
                postFile.setHeader("Authorization", getCkanToken());
                MultipartEntity mpEntity = new MultipartEntity(HttpMultipartMode.STRICT);

                //JSONArray fields = obj.getJSONArray("fields");
                Iterator<JsonNode> fields = obj.get("fields").elements();
                while (fields.hasNext()) {
                    JsonNode fieldObj = fields.next();
                    //JSONObject fieldObj = fields.getJSONObject(i);
                    String fieldName = fieldObj.get("name").asText();
                    String fieldValue = fieldObj.get("value").asText();
                    if (fieldName.equals("key")) {
                        filekey = fieldValue;
                    }
                    mpEntity.addPart(fieldName,
                            new StringBody(fieldValue, "multipart/form-data", Charset.forName("UTF-8")));
                }

                /*
                 for (int i = 0; i < fields.length(); i++) {
                 //JSONObject fieldObj = fields.getJSONObject(i);
                 JSONObject fieldObj = fields.getJSONObject(i);
                 String fieldName = fieldObj.getString("name");
                 String fieldValue = fieldObj.getString("value");
                 if (fieldName.equals("key")) {
                 filekey = fieldValue;
                 }
                 mpEntity.addPart(fieldName, new StringBody(fieldValue, "multipart/form-data", Charset.forName("UTF-8")));                    
                 }
                 */
                //   assure that we got the file key
                if (filekey == null) {
                    throw new RuntimeException(
                            "failed to get the file key from CKAN storage form API. the response from " + formUrl
                                    + " was: " + os.toString());
                }

                //the file should be the last part
                //hack... StringBody didn't work with large files
                mpEntity.addPart("file", new ByteArrayBody(fileContent.getBytes(Charset.forName("UTF-8")),
                        "multipart/form-data", fileLabel));

                postFile.setEntity(mpEntity);

                HttpResponse fileUploadResponse = client.execute(postFile);

                //check if the response status code was in the 200 range
                if (fileUploadResponse.getStatusLine().getStatusCode() < 200
                        || fileUploadResponse.getStatusLine().getStatusCode() >= 300) {
                    throw new RuntimeException("failed to add the file to CKAN storage. response status line from "
                            + uploadFileUrl + " was: " + fileUploadResponse.getStatusLine());
                }
                return getCatalogUrl() + "/storage/f/" + filekey;

                //return CKAN_STORAGE_FILES_BASE_URI + filekey;
            }
            throw new RuntimeException("failed to get form details from CKAN storage. response line was: "
                    + formFields.getStatusLine());
        } catch (IOException ioe) {
            throw new RuntimeException("failed to upload file to CKAN Storage ", ioe);
        }
    }

    public static ExperimentalCkanClient of(CkanClient client) {
        return new ExperimentalCkanClient(client.getCatalogUrl(), client.getCkanToken());
    }
}