/* * Copyright (C) 2005 - 2014 Jaspersoft Corporation. All rights reserved. * http://www.jaspersoft.com. * * Unless you have purchased a commercial license agreement from Jaspersoft, * the following license terms apply: * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program.  If not, see <http://www.gnu.org/licenses/>. */ package com.jaspersoft.jasperserver.jaxrs.client.apiadapters.resources; import com.jaspersoft.jasperserver.dto.common.PatchDescriptor; import com.jaspersoft.jasperserver.dto.resources.ClientFile; import com.jaspersoft.jasperserver.dto.resources.ClientResource; import com.jaspersoft.jasperserver.dto.resources.ClientSemanticLayerDataSource; import com.jaspersoft.jasperserver.dto.resources.ResourceMediaType; import com.jaspersoft.jasperserver.jaxrs.client.apiadapters.AbstractAdapter; import com.jaspersoft.jasperserver.jaxrs.client.core.Callback; import com.jaspersoft.jasperserver.jaxrs.client.core.JerseyRequest; import com.jaspersoft.jasperserver.jaxrs.client.core.MimeTypeUtil; import com.jaspersoft.jasperserver.jaxrs.client.core.RequestExecution; import com.jaspersoft.jasperserver.jaxrs.client.core.SessionStorage; import com.jaspersoft.jasperserver.jaxrs.client.core.ThreadPoolUtil; import com.jaspersoft.jasperserver.jaxrs.client.core.enums.MimeType; import com.jaspersoft.jasperserver.jaxrs.client.core.exceptions.handling.DefaultErrorHandler; import com.jaspersoft.jasperserver.jaxrs.client.core.operationresult.OperationResult; import com.sun.jersey.multipart.FormDataMultiPart; import java.io.File; import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedHashMap; import javax.ws.rs.core.MultivaluedMap; public class SingleResourceAdapter extends AbstractAdapter { public static final String SERVICE_URI = "resources"; public static final String REGEX = "/"; private final String resourceUri; private final MultivaluedMap<String, String> params; private ArrayList<String> path = new ArrayList<String>(); public SingleResourceAdapter(SessionStorage sessionStorage, String resourceUri) { super(sessionStorage); this.resourceUri = resourceUri; this.params = new MultivaluedHashMap<String, String>(); } public SingleResourceAdapter parameter(ResourceServiceParameter param, String value) { params.add(param.getName(), value); return this; } public OperationResult<ClientResource> details() { JerseyRequest<ClientResource> request = prepareDetailsRequest(); return request.get(); } public <R> RequestExecution asyncDetails(final Callback<OperationResult<ClientResource>, R> callback) { final JerseyRequest<ClientResource> request = prepareDetailsRequest(); RequestExecution task = new RequestExecution(new Runnable() { @Override public void run() { callback.execute(request.get()); } }); ThreadPoolUtil.runAsynchronously(task); return task; } private JerseyRequest<ClientResource> prepareDetailsRequest() { JerseyRequest<ClientResource> request = buildRequest(ClientResource.class); request.addParams(params); if (isRootFolder(resourceUri)) { request.setAccept(sessionStorage.getConfiguration().getAcceptMimeType().equals(MimeType.JSON) ? ResourceMediaType.FOLDER_JSON : ResourceMediaType.FOLDER_XML); } else { request.setAccept(sessionStorage.getConfiguration().getAcceptMimeType().equals(MimeType.JSON) ? ResourceMediaType.FILE_JSON : ResourceMediaType.FILE_XML); } return request; } private boolean isRootFolder(String resourceUri) { return "/".equals(resourceUri) || "".equals(resourceUri); } public OperationResult<InputStream> downloadBinary() { return buildRequest(InputStream.class).get(); } public <R> RequestExecution asyncDownloadBinary(final Callback<OperationResult<InputStream>, R> callback) { final JerseyRequest<InputStream> request = buildRequest(InputStream.class); RequestExecution task = new RequestExecution(new Runnable() { @Override public void run() { callback.execute(request.get()); } }); ThreadPoolUtil.runAsynchronously(task); return task; } public OperationResult<ClientResource> createOrUpdate(ClientResource resource) { return prepareCreateOrUpdateRequest(resource).put(resource); } public <R> RequestExecution asyncCreateOrUpdate(final ClientResource resource, final Callback<OperationResult<ClientResource>, R> callback) { final JerseyRequest<ClientResource> request = prepareCreateOrUpdateRequest(resource); RequestExecution task = new RequestExecution(new Runnable() { @Override public void run() { callback.execute(request.put(resource)); } }); ThreadPoolUtil.runAsynchronously(task); return task; } public OperationResult<ClientResource> createNew(ClientResource resource) { return prepareCreateOrUpdateRequest(resource).post(resource); } public <R> RequestExecution asyncCreateNew(final ClientResource resource, final Callback<OperationResult<ClientResource>, R> callback) { final JerseyRequest<ClientResource> request = prepareCreateOrUpdateRequest(resource); RequestExecution task = new RequestExecution(new Runnable() { @Override public void run() { callback.execute(request.post(resource)); } }); ThreadPoolUtil.runAsynchronously(task); return task; } private JerseyRequest<ClientResource> prepareCreateOrUpdateRequest(ClientResource resource) { Class<? extends ClientResource> resourceType = ResourcesTypeResolverUtil.getResourceType(resource); JerseyRequest<? extends ClientResource> request = buildRequest(resourceType); request.setContentType(MimeTypeUtil.toCorrectContentMime(sessionStorage.getConfiguration(), ResourcesTypeResolverUtil.getMimeType(resourceType))); request.addParams(params); return (JerseyRequest<ClientResource>) request; } public OperationResult<ClientResource> copyFrom(String fromUri) { return copyOrMove(false, fromUri); } public OperationResult<ClientResource> moveFrom(String fromUri) { return copyOrMove(true, fromUri); } private OperationResult<ClientResource> copyOrMove(boolean moving, String fromUri) { JerseyRequest<ClientResource> request = prepareCopyOrMoveRequest(fromUri); if (moving) { return request.put(""); } else { return request.post(null); } } public <R> RequestExecution asyncCopyOrMove(final boolean moving, final String fromUri, final Callback<OperationResult<ClientResource>, R> callback) { final JerseyRequest<ClientResource> request = prepareCopyOrMoveRequest(fromUri); RequestExecution task = new RequestExecution(new Runnable() { @Override public void run() { OperationResult<ClientResource> result; if (moving) { result = request.put(""); } else { result = request.post(null); } callback.execute(result); } }); ThreadPoolUtil.runAsynchronously(task); return task; } private JerseyRequest<ClientResource> prepareCopyOrMoveRequest(String fromUri) { JerseyRequest<ClientResource> request = buildRequest(ClientResource.class); request.addParams(params); request.addHeader("Content-Location", fromUri); return request; } /** * Allows to upload resource with MultiPart request. * * @param multipartResource form * @param clazz entity class * @param <T> type of entity class * @return result instance */ public <T> OperationResult<T> uploadMultipartResource(FormDataMultiPart multipartResource, Class<T> clazz) { JerseyRequest<T> request = buildRequest(clazz); request.setContentType(MediaType.MULTIPART_FORM_DATA); return request.post(multipartResource); } public <T> OperationResult<T> get(Class<T> clazz) { JerseyRequest<T> request = buildRequest(clazz); if (isRootFolder(resourceUri)) { request.setAccept(sessionStorage.getConfiguration().getAcceptMimeType().equals(MimeType.JSON) ? ResourceMediaType.FOLDER_JSON : ResourceMediaType.FOLDER_XML); } else { request.setAccept(sessionStorage.getConfiguration().getAcceptMimeType().equals(MimeType.JSON) ? ResourceMediaType.FILE_JSON : ResourceMediaType.FILE_XML); } return request.get(); } public OperationResult<ClientFile> uploadFile(File fileContent, ClientFile.FileType fileType, String label, String description) { FormDataMultiPart form = prepareUploadForm(fileContent, fileType, label, description); JerseyRequest<ClientFile> request = prepareUploadFileRequest(); return request.post(form); } public <R> RequestExecution asyncUploadFile(final File fileContent, final ClientFile.FileType fileType, final String label, final String description, final Callback<OperationResult<ClientFile>, R> callback) { final FormDataMultiPart form = prepareUploadForm(fileContent, fileType, label, description); final JerseyRequest<ClientFile> request = prepareUploadFileRequest(); RequestExecution task = new RequestExecution(new Runnable() { @Override public void run() { callback.execute(request.post(form)); } }); ThreadPoolUtil.runAsynchronously(task); return task; } private FormDataMultiPart prepareUploadForm(File fileContent, ClientFile.FileType fileType, String label, String description) { FormDataMultiPart form = new FormDataMultiPart(); form .field("data", fileContent, MediaType.WILDCARD_TYPE) .field("label", label) .field("description", description) .field("type", fileType.name()); return form; } private JerseyRequest<ClientFile> prepareUploadFileRequest() { JerseyRequest<ClientFile> request = buildRequest(ClientFile.class); request.addParams(params); request.setContentType(MediaType.MULTIPART_FORM_DATA); return request; } /** * Jersey request setup. Generified with a proper entity. * * @return JerseyRequest instance */ private JerseyRequest<ClientSemanticLayerDataSource> prepareUploadResourcesRequest() { JerseyRequest<ClientSemanticLayerDataSource> request = buildRequest(ClientSemanticLayerDataSource.class); request.setContentType(MediaType.MULTIPART_FORM_DATA); return request; } public OperationResult delete() { JerseyRequest request = buildRequest(Object.class); return request.delete(); } public <R> RequestExecution asyncDelete(final Callback<OperationResult, R> callback) { final JerseyRequest request = buildRequest(Object.class); RequestExecution task = new RequestExecution(new Runnable() { @Override public void run() { callback.execute(request.delete()); } }); ThreadPoolUtil.runAsynchronously(task); return task; } public OperationResult<ClientResource> patchResource(PatchDescriptor descriptor) { throw new UnsupportedOperationException("Server doesn't return proper MIME-type inFolder resolve entity type"); } public <ResourceType extends ClientResource> OperationResult<ResourceType> patchResource(Class<ResourceType> resourceTypeClass, PatchDescriptor descriptor) { JerseyRequest<ResourceType> request = preparePatchResourceRequest(resourceTypeClass); return request.post(descriptor); } public <ResourceType extends ClientResource, R> RequestExecution asyncPatchResource(final Class<ResourceType> resourceTypeClass, final PatchDescriptor descriptor, final Callback<OperationResult<ResourceType>, R> callback) { final JerseyRequest request = preparePatchResourceRequest(resourceTypeClass); RequestExecution task = new RequestExecution(new Runnable() { @Override public void run() { callback.execute(request.post(descriptor)); } }); ThreadPoolUtil.runAsynchronously(task); return task; } private <ResourceType extends ClientResource> JerseyRequest<ResourceType> preparePatchResourceRequest(Class<ResourceType> resourceTypeClass) { JerseyRequest<ResourceType> request = buildRequest(resourceTypeClass); request.setAccept(MimeTypeUtil.toCorrectContentMime(sessionStorage.getConfiguration(), ResourcesTypeResolverUtil.getMimeType(resourceTypeClass))); request.addHeader("X-HTTP-Method-Override", "PATCH"); return request; } private <P> JerseyRequest<P> buildRequest(Class<P> clazz) { path.add(SERVICE_URI); if (!resourceUri.equals(REGEX)) { path.addAll(Arrays.asList(resourceUri.split(REGEX))); } return JerseyRequest.buildRequest(sessionStorage, clazz, path.toArray(new String[path.size()]), new DefaultErrorHandler()); } }