Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.sap.cloud.sdk.odatav2.connectivity.internal.ODataConnectivityUtil Maven / Gradle / Ivy
/*******************************************************************************
* (c) 201X SAP SE or an SAP affiliate company. All rights reserved.
******************************************************************************/
package com.sap.cloud.sdk.odatav2.connectivity.internal;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.HttpClientUtils;
import org.apache.olingo.odata2.api.edm.Edm;
import org.apache.olingo.odata2.api.edm.EdmEntityType;
import org.apache.olingo.odata2.api.edm.EdmException;
import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
import org.apache.olingo.odata2.api.edm.EdmProperty;
import org.apache.olingo.odata2.api.edm.EdmSimpleType;
import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
import org.apache.olingo.odata2.client.api.ep.Entity;
import org.apache.olingo.odata2.client.api.ep.EntityCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.sap.cloud.sdk.cloudplatform.cache.CacheKey;
import com.sap.cloud.sdk.odatav2.connectivity.ErrorResultHandler;
import com.sap.cloud.sdk.odatav2.connectivity.ODataException;
import com.sap.cloud.sdk.odatav2.connectivity.ODataExceptionType;
import com.sap.cloud.sdk.odatav2.connectivity.cache.metadata.GuavaMetadataCache;
import com.sap.cloud.sdk.odatav2.connectivity.cache.metadata.MetadataCache;
public class ODataConnectivityUtil {
private static Logger logger = LoggerFactory.getLogger(ODataConnectivityUtil.class);
public static final String CSRF_HEADER = "x-csrf-token";
private static MetadataCache metadataCache = new GuavaMetadataCache();
public static final String SEPARATOR_PATH = "/";
static final int HTTP_CODE_ERROR_MIN = 400;
static final int HTTP_CODE_ERROR_MAX = 599;
private static final int HTTP_CODE_METHOD_NOT_ALLOWED = 405;
public static EdmWithCSRF readMetadataWithCSRF(String serviceUri, HttpClient httpClient,
Map headers, ErrorResultHandler> errorHandler, Boolean cacheMetadata,
URL metadataFilePath, CacheKey cacheKey, Boolean isCacheRefresh)
throws ClientProtocolException, IOException, ODataException {
EdmWithCSRF edmWithCSRF = null;
HttpResponse httpResponse = null;
HttpHead httpGet = new HttpHead(serviceUri);
try {
Edm edm = metadataCache.getEdm(serviceUri + "/$metadata", httpClient, headers, errorHandler, cacheMetadata,
metadataFilePath, cacheKey, isCacheRefresh);
httpGet.setHeader(CSRF_HEADER, "Fetch");
if (headers != null) {
for (Entry e : headers.entrySet()) {
httpGet.addHeader(e.getKey(), e.getValue());
}
}
httpResponse = httpClient.execute(httpGet);
ODataConnectivityUtil.checkHttpResponseForCSRF(httpResponse, errorHandler);
// TODO - Code for null check.
Header csrfHeader = httpResponse.getFirstHeader(CSRF_HEADER);
String csrfToken = csrfHeader == null ? null : csrfHeader.getValue();
edmWithCSRF = new EdmWithCSRF(edm, csrfToken);
return edmWithCSRF;
} catch (Exception e) {
logger.error("Error occurred during create operation of Type : " + e);
throw e;
} finally {
HttpClientUtils.closeQuietly(httpResponse);
ODataConnectivityUtil.closeQuietly(httpResponse, httpGet);
}
}
public static EdmWithCSRF readMetadataWithCSRF(String serviceUri, HttpClient httpClient,
Map headers, ErrorResultHandler> errorHandler, Boolean cacheMetadata,
URL metadataFilePath) throws ClientProtocolException, IOException, ODataException {
return readMetadataWithCSRF(serviceUri, httpClient, headers, errorHandler, cacheMetadata, metadataFilePath,
null, false);
}
public static String convertKeyValuesToString(Map keys, EdmEntityType entityType)
throws ODataException, EdmException {
String keyPredicateString = "";
for (Entry e : keys.entrySet()) {
if (!keyPredicateString.isEmpty())
keyPredicateString += ',';
String key = e.getKey();
Object value = e.getValue();
EdmProperty prop = (EdmProperty) entityType.getProperty(key);
if (prop == null)
throw new ODataException(ODataExceptionType.KEY_NOT_PRESENT, "No such key property. " + key, null);
EdmSimpleType type = (EdmSimpleType) (prop.getType());
String convertedValue;
try {
if("String".equals(type.getName()) && value != null){
value = UrlEncoder.encode(value.toString());
}
convertedValue = type.toUriLiteral(type.valueToString(value, EdmLiteralKind.DEFAULT, prop.getFacets()));
} catch (EdmSimpleTypeException e1) {
throw new ODataException(ODataExceptionType.BAD_KEY_VALUE, e1.getMessage(), e1);
}
keyPredicateString += key + '=' + convertedValue;
}
return keyPredicateString;
}
public static Entity addPropertiesToEntity(Map properties, EdmEntityType entityType)
throws EdmException, ODataException {
Entity entity = new Entity();
List navigationProperties = entityType.getNavigationPropertyNames();
List propertiesInEntity = entityType.getPropertyNames();
for (Iterator keySetIterator = properties.keySet().iterator(); keySetIterator.hasNext();) {
String propertyName = keySetIterator.next().toString();
// Handled Deep Insert for Multilevel
if (navigationProperties.contains(propertyName)) {
EdmNavigationProperty navigationProperty = (EdmNavigationProperty) entityType.getProperty(propertyName);
EdmEntityType targetType = navigationProperty.getRelationship().getEnd(navigationProperty.getToRole())
.getEntityType();
if (navigationProperty.getMultiplicity().equals(EdmMultiplicity.MANY)) {
List> childEntities = null;
if (properties.get(propertyName) instanceof List)
childEntities = (List>) properties.get(propertyName);
else if (properties.get(propertyName) instanceof Map) {
childEntities = new ArrayList>();
childEntities.add((Map) properties.get(propertyName));
}
else if (properties.get(propertyName) instanceof ODataFeed){
ODataFeed feed = (ODataFeed) properties.get(propertyName);
childEntities = new ArrayList>();
for (ODataEntry feedEntry : feed.getEntries()) {
childEntities.add(mapEntryToMap(feedEntry));
}
}
EntityCollection deepInsertChildren = new EntityCollection();
for (Map entry : childEntities) {
deepInsertChildren.addEntity(addPropertiesToEntity(entry, targetType));
}
entity.addNavigation(propertyName, deepInsertChildren);
} else {
Map childEntity = null;
if (properties.get(propertyName) instanceof List)
childEntity = ((List>) properties.get(propertyName)).get(0);
else if (properties.get(propertyName) instanceof Map) {
childEntity = (Map) properties.get(propertyName);
}
else if (properties.get(propertyName) instanceof ODataEntry){
ODataEntry entryFeed = (ODataEntry) properties.get(propertyName);
childEntity = (Map) mapEntryToMap(entryFeed);
}
entity.addNavigation(propertyName, addPropertiesToEntity(childEntity, targetType));
}
} else if (!propertiesInEntity.contains(propertyName)) {
throw new ODataException(ODataExceptionType.INVALID_PROPERTY_NAME,
"No property with name " + propertyName + " present in the entity", null);
} else if (properties.get(propertyName) instanceof Map) { // Complex
// Type
entity.addProperty(propertyName,
addPropertiesToMap((Map) properties.get(propertyName)));
} else
entity.addProperty(propertyName, properties.get(propertyName));
}
return entity;
}
private static Map mapEntryToMap(ODataEntry entry) {
Map finalResult = new HashMap<>();
for (Entry property : entry.getProperties().entrySet()) {
if (property.getValue() instanceof ODataFeed) {
ODataFeed feedExpand = (ODataFeed) property.getValue();
List> allChildren = new ArrayList>();
for (ODataEntry feedEntry : feedExpand.getEntries()) {
allChildren.add(mapEntryToMap(feedEntry));
}
finalResult.put(property.getKey(), allChildren);
} else if (property.getValue() instanceof ODataEntry) {
ODataEntry entryFeed = (ODataEntry) property.getValue();
finalResult.put(property.getKey(), mapEntryToMap(entryFeed));
} else {
finalResult.put(property.getKey(), property.getValue());
}
}
return finalResult;
}
@SuppressWarnings("unchecked")
private static Map addPropertiesToMap(Map complexProperties) {
Map returnedComplexType = new HashMap<>();
for (Entry entry : complexProperties.entrySet()) {
if (entry.getValue() instanceof Map) {
returnedComplexType.put(entry.getKey(), addPropertiesToMap((Map) entry.getValue()));
} else {// it is a simple property
returnedComplexType.put(entry.getKey(), entry.getValue());
}
}
return returnedComplexType;
}
/**
* Checks the HttpStatus code and returns an ODataException object if it falls
* between 400 and 599.
*
* @param response HttpResponse object
* @param errorHandler
* @throws ODataException
*/
public static void checkHttpStatus(final HttpResponse response, ErrorResultHandler> errorHandler)
throws ODataException {
if (errorHandler == null)
errorHandler = (ErrorResultHandler>) new ODataExceptionInternalResultHandler();
final int httpStatusCode = response.getStatusLine().getStatusCode();
if (HTTP_CODE_ERROR_MIN <= httpStatusCode && httpStatusCode <= HTTP_CODE_ERROR_MAX) {
String fullResponse = "";
try {
if (response.getEntity() != null) {
fullResponse = IOUtils.toString(response.getEntity().getContent(), "UTF-8");
}
if (logger.isDebugEnabled()) {
logger.debug("OData service response: " + fullResponse + ".");
}
} catch (final IOException e) {
fullResponse = "Failed to load error page from OData service: " + e.getMessage() + ".";
}finally{
HttpClientUtils.closeQuietly(response);
}
if (errorHandler instanceof ODataExceptionInternalResultHandler) {
throw errorHandler.createError(fullResponse, (Object) response, httpStatusCode);
} else {
throw errorHandler.createError(fullResponse, null, httpStatusCode);
}
}
}
/**
* Check if the Response is an invalid response but the CSRF is returned by the
* server In case some servers return 405 and CSRF Token is returned, we
* consider such cases as success
*
* @param response
* @param errorHandler
* @throws ODataException
*/
private static void checkHttpResponseForCSRF(final HttpResponse response, ErrorResultHandler> errorHandler)
throws ODataException {
if (errorHandler == null)
errorHandler = (ErrorResultHandler>) new ODataExceptionInternalResultHandler();
final int httpStatusCode = response.getStatusLine().getStatusCode();
final Header csrfHeader = response.getFirstHeader(CSRF_HEADER);
if (httpStatusCode == HTTP_CODE_METHOD_NOT_ALLOWED && csrfHeader != null) {
return;
}
checkHttpStatus(response, errorHandler);
}
public static void closeQuietly(HttpResponse httpResponse, HttpRequestBase request) {
HttpClientUtils.closeQuietly(httpResponse);
request.releaseConnection();
}
@Deprecated
public static void safeCloseHttpResponse(HttpResponse httpResponse) {
if (httpResponse != null) {
HttpEntity entity = httpResponse.getEntity();
try {
if (entity != null && entity.isStreaming()) {
InputStream instream = entity.getContent();
if (instream != null) {
instream.close();
}
}
// EntityUtils.consume(entity);
} catch (final IOException ex) {
logger.info("IOException while closing HttpResponse entity.getContent()");
} catch (final IllegalStateException e) {
logger.info("IllegalStateException while closing HttpResponse entity.getContent()");
}
}
}
public static InputStream getObjectStream(Object entity) {
InputStream inputStream = null;
if (entity instanceof String) {
inputStream = new ByteArrayInputStream(((String) entity).getBytes(StandardCharsets.UTF_8));
} else {
inputStream = (InputStream) entity;
}
return inputStream;
}
public static String withSeparator(final String separator, final String... parts) {
final StringBuilder result = new StringBuilder();
for (String s : parts) {
if (!StringUtils.isEmpty(s)) {
s = StringUtils.prependIfMissing(s, separator);
s = StringUtils.removeEnd(s, separator);
result.append(s);
}
}
return result.toString();
}
}