Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 org.apache.olingo.client.core.uri; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.math.BigDecimal; import java.net.URI; import java.net.URISyntaxException; import java.net.URLEncoder; import java.sql.Timestamp; import java.util.Calendar; import java.util.Collection; import java.util.Iterator; import java.util.Map; import java.util.UUID; import java.util.regex.Pattern; import javax.xml.datatype.Duration; import org.apache.commons.codec.binary.Hex; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpEntity; import org.apache.http.client.utils.URIBuilder; import org.apache.http.entity.AbstractHttpEntity; import org.apache.http.entity.ByteArrayEntity; import org.apache.http.entity.InputStreamEntity; import org.apache.olingo.client.api.ODataClient; import org.apache.olingo.client.api.http.HttpClientFactory; import org.apache.olingo.client.api.http.WrappingHttpClientFactory; import org.apache.olingo.client.api.uri.SegmentType; import org.apache.olingo.client.core.http.BasicAuthHttpClientFactory; import org.apache.olingo.commons.api.Constants; import org.apache.olingo.client.api.domain.ClientValue; import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException; import org.apache.olingo.commons.api.edm.geo.Geospatial; import org.apache.olingo.commons.core.edm.primitivetype.EdmBinary; import org.apache.olingo.commons.core.edm.primitivetype.EdmDateTimeOffset; import org.apache.olingo.commons.core.edm.primitivetype.EdmDecimal; import org.apache.olingo.commons.core.edm.primitivetype.EdmDouble; import org.apache.olingo.commons.core.edm.primitivetype.EdmDuration; import org.apache.olingo.commons.core.edm.primitivetype.EdmInt64; import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory; import org.apache.olingo.commons.core.edm.primitivetype.EdmSingle; /** * URI utilities. */ public final class URIUtils { /** * Logger. */ // private static final Logger LOG = LoggerFactory.getLogger(URIUtils.class); private static final Pattern ENUM_VALUE = Pattern.compile("(.+\\.)?.+'.+'"); private URIUtils() { // Empty private constructor for static utility classes } /** * Build URI starting from the given base and href. * <br/> * If href is absolute or base is null then base will be ignored. * * @param base URI prefix. * @param href URI suffix. * @return built URI. */ public static URI getURI(final String base, final String href) { if (href == null) { throw new IllegalArgumentException("Null link provided"); } URI uri = URI.create(href); if (!uri.isAbsolute() && base != null) { uri = URI.create(base + "/" + href); } return uri.normalize(); } /** * Build URI starting from the given base and href. * <br/> * If href is absolute or base is null then base will be ignored. * * @param base URI prefix. * @param href URI suffix. * @return built URI. */ public static URI getURI(final URI base, final URI href) { if (href == null) { throw new IllegalArgumentException("Null link provided"); } return getURI(base, href.toASCIIString()); } /** * Build URI starting from the given base and href. * <br/> * If href is absolute or base is null then base will be ignored. * * @param base URI prefix. * @param href URI suffix. * @return built URI. */ public static URI getURI(final URI base, final String href) { if (href == null) { throw new IllegalArgumentException("Null link provided"); } URI uri = URI.create(href); if (!uri.isAbsolute() && base != null) { uri = URI.create(base.toASCIIString() + "/" + href); } return uri.normalize(); } private static String timestamp(final Timestamp timestamp) throws UnsupportedEncodingException, EdmPrimitiveTypeException { return URLEncoder.encode(EdmDateTimeOffset.getInstance().valueToString(timestamp, null, null, Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, null), Constants.UTF8); } private static String calendar(final Calendar calendar) throws UnsupportedEncodingException, EdmPrimitiveTypeException { return URLEncoder.encode(EdmDateTimeOffset.getInstance().valueToString(calendar, null, null, Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, null), Constants.UTF8); } private static String duration(final Duration duration) throws UnsupportedEncodingException, EdmPrimitiveTypeException { return EdmDuration.getInstance() .toUriLiteral(URLEncoder.encode(EdmDuration.getInstance().valueToString(duration, null, null, Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, null), Constants.UTF8)); } private static String quoteString(final String string, final boolean singleQuoteEscape) throws UnsupportedEncodingException { return ENUM_VALUE.matcher(string).matches() ? string : singleQuoteEscape ? "'" + string + "'" : "\"" + string + "\""; } /** * Turns primitive values into their respective URI representation. * * @param obj primitive value * @return URI representation */ public static String escape(final Object obj) { return escape(obj, true); } private static String escape(final Object obj, final boolean singleQuoteEscape) { String value; try { if (obj == null) { value = Constants.ATTR_NULL; } else if (obj instanceof Collection) { final StringBuilder buffer = new StringBuilder("["); for (@SuppressWarnings("unchecked") final Iterator<Object> itor = ((Collection<Object>) obj).iterator(); itor.hasNext();) { buffer.append(escape(itor.next(), false)); if (itor.hasNext()) { buffer.append(','); } } buffer.append(']'); value = buffer.toString(); } else if (obj instanceof Map) { final StringBuilder buffer = new StringBuilder("{"); for (@SuppressWarnings("unchecked") final Iterator<Map.Entry<String, Object>> itor = ((Map<String, Object>) obj).entrySet() .iterator(); itor.hasNext();) { final Map.Entry<String, Object> entry = itor.next(); buffer.append("\"").append(entry.getKey()).append("\""); buffer.append(':').append(escape(entry.getValue(), false)); if (itor.hasNext()) { buffer.append(','); } } buffer.append('}'); value = buffer.toString(); } else { value = (obj instanceof ParameterAlias) ? "@" + ((ParameterAlias) obj).getAlias() : (obj instanceof Boolean) ? BooleanUtils.toStringTrueFalse((Boolean) obj) : (obj instanceof UUID) ? obj.toString() : (obj instanceof byte[]) ? EdmBinary.getInstance() .toUriLiteral(Hex.encodeHexString((byte[]) obj)) : (obj instanceof Timestamp) ? timestamp((Timestamp) obj) : (obj instanceof Calendar) ? calendar((Calendar) obj) : (obj instanceof Duration) ? duration((Duration) obj) : (obj instanceof BigDecimal) ? EdmDecimal .getInstance().valueToString(obj, null, null, Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, null) : (obj instanceof Double) ? EdmDouble.getInstance() .valueToString(obj, null, null, Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, null) : (obj instanceof Float) ? EdmSingle .getInstance() .valueToString( obj, null, null, Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, null) : (obj instanceof Long) ? EdmInt64 .getInstance() .valueToString( obj, null, null, Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, null) : (obj instanceof Geospatial) ? URLEncoder .encode(EdmPrimitiveTypeFactory .getInstance( ((Geospatial) obj) .getEdmPrimitiveTypeKind()) .valueToString( obj, null, null, Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, null), Constants.UTF8) : (obj instanceof String) ? quoteString( (String) obj, singleQuoteEscape) : obj.toString(); } } catch (final EdmPrimitiveTypeException e) { value = obj.toString(); } catch (final UnsupportedEncodingException e) { value = obj.toString(); } return value; } public static boolean shouldUseRepeatableHttpBodyEntry(final ODataClient client) { // returns true for authentication request in case of http401 which needs retry so requires being repeatable. HttpClientFactory httpclientFactory = client.getConfiguration().getHttpClientFactory(); if (httpclientFactory instanceof BasicAuthHttpClientFactory) { return true; } else if (httpclientFactory instanceof WrappingHttpClientFactory) { WrappingHttpClientFactory tmp = (WrappingHttpClientFactory) httpclientFactory; if (tmp.getWrappedHttpClientFactory() instanceof BasicAuthHttpClientFactory) { return true; } } return false; } public static HttpEntity buildInputStreamEntity(final ODataClient client, final InputStream input) { AbstractHttpEntity entity; boolean useChunked = client.getConfiguration().isUseChuncked(); if (shouldUseRepeatableHttpBodyEntry(client) || !useChunked) { byte[] bytes = new byte[0]; try { bytes = IOUtils.toByteArray(input); IOUtils.closeQuietly(input); } catch (IOException e) { throw new RuntimeException("While reading input for not chunked encoding", e); } entity = new ByteArrayEntity(bytes); } else { entity = new InputStreamEntity(input, -1); } if (!useChunked && entity.getContentLength() < 0) { useChunked = true; } // both entities can be sent in chunked way or not entity.setChunked(useChunked); return entity; } public static URI addValueSegment(final URI uri) { final URI res; if (uri.getPath().endsWith(SegmentType.VALUE.getValue())) { res = uri; } else { try { res = new URIBuilder(uri).setPath(uri.getPath() + "/" + SegmentType.VALUE.getValue()).build(); } catch (URISyntaxException e) { throw new IllegalArgumentException(e); } } return res; } public static URI buildFunctionInvokeURI(final URI uri, final Map<String, ClientValue> parameters) { final String rawQuery = uri.getRawQuery(); String baseURI = StringUtils.substringBefore(uri.toASCIIString(), "?" + rawQuery); if (baseURI.endsWith("()")) { baseURI = baseURI.substring(0, baseURI.length() - 2); } final StringBuilder inlineParams = new StringBuilder(); for (Map.Entry<String, ClientValue> param : parameters.entrySet()) { inlineParams.append(param.getKey()).append("="); Object value = null; if (param.getValue().isPrimitive()) { value = param.getValue().asPrimitive().toValue(); } else if (param.getValue().isComplex()) { value = param.getValue().asComplex().asJavaMap(); } else if (param.getValue().isCollection()) { value = param.getValue().asCollection().asJavaCollection(); } else if (param.getValue().isEnum()) { value = param.getValue().asEnum().toString(); } inlineParams.append(URIUtils.escape(value)).append(','); } if (inlineParams.length() > 0) { inlineParams.deleteCharAt(inlineParams.length() - 1); } try { return URI.create(baseURI + "(" + URLEncoder.encode(inlineParams.toString(), Constants.UTF8) + ")" + (StringUtils.isNotBlank(rawQuery) ? "?" + rawQuery : StringUtils.EMPTY)); } catch (UnsupportedEncodingException e) { throw new IllegalArgumentException("While adding GET parameters", e); } } }