All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.wink.common.internal.UriBuilderImpl Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 * 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.wink.common.internal;

import java.lang.reflect.Method;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.ws.rs.Path;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.PathSegment;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriBuilderException;

import org.apache.wink.common.internal.i18n.Messages;
import org.apache.wink.common.internal.uri.UriEncoder;
import org.apache.wink.common.internal.uritemplate.JaxRsUriTemplateProcessor;
import org.apache.wink.common.internal.utils.UriHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class UriBuilderImpl extends UriBuilder implements Cloneable {

    private static final Logger            logger = LoggerFactory.getLogger(UriBuilderImpl.class);

    private String                         scheme;
    private String                         userInfo;
    private String                         host;
    private int                            port;
    private String                         fragment;
    private List              segments;
    private MultivaluedMap query;
    private String                         schemeSpecificPart;
    private boolean                        isFirstCall;

    public UriBuilderImpl() {
        reset();
        isFirstCall = true;
    }

    public void reset() {
        logger.trace("Entered reset"); //$NON-NLS-1$
        scheme = null;
        resetSchemeSpecificPart();
        query = null;
        fragment = null;
        logger.trace("Exit reset"); //$NON-NLS-1$
    }

    private void resetSchemeSpecificPart() {
        logger.trace("Entered resetSchemeSpecificPart"); //$NON-NLS-1$
        schemeSpecificPart = null;
        userInfo = null;
        host = null;
        port = -1;
        segments = null;
        logger.trace("Exit resetSchemeSpecificPart"); //$NON-NLS-1$
    }

    private List getPathSegments() {
        if (segments == null) {
            segments = new ArrayList();
        }
        logger.trace("getPathSegments returning {}", segments); //$NON-NLS-1$
        return segments;
    }

    private MultivaluedMap getQuery() {
        if (query == null) {
            query = new MultivaluedMapImpl();
        }
        logger.trace("getQuery returning {}", query); //$NON-NLS-1$
        return query;
    }

    private String constructPathString() {
        if (segments == null) {
            logger.trace("constructPathString() returning null because null segments"); //$NON-NLS-1$
            return null;
        }

        StringBuilder path = new StringBuilder();
        for (PathSegment segment : segments) {
            String segmentStr = segment.toString();
            path.append("/"); //$NON-NLS-1$
            path.append(segmentStr);
            logger.trace("appending {} from path segment to path", segmentStr); //$NON-NLS-1$
        }

        String str = path.toString();
        logger.trace("constructPathString() returning {}", str); //$NON-NLS-1$
        return str;
    }

    private String constructQueryString() {
        if (query == null) {
            logger.trace("constructQueryString returning null beause null"); //$NON-NLS-1$
            return null;
        }
        if (query.size() == 0) {
            logger.trace("constructQueryString returning empty string because string size is 0"); //$NON-NLS-1$
            return ""; //$NON-NLS-1$
        }
        String queryStr = "?" + MultivaluedMapImpl.toString(query, "&"); //$NON-NLS-1$ //$NON-NLS-2$
        logger.trace("constructQueryString returning {}", queryStr); //$NON-NLS-1$
        return queryStr;
    }

    private Set getVariableNamesList() {
        logger.trace("getVariableNamesList() entry"); //$NON-NLS-1$
        String constructedPath = constructPathString();
        String constructedQuery = constructQueryString();
        String uriStr =
            UriHelper.contructUri(scheme,
                                  userInfo,
                                  host,
                                  port,
                                  constructedPath,
                                  constructedQuery,
                                  fragment);
        JaxRsUriTemplateProcessor uriTemplate = new JaxRsUriTemplateProcessor(uriStr);
        Set ret = uriTemplate.getVariableNames();
        logger.trace("getVariableNamesList() returning {}", ret); //$NON-NLS-1$
        return ret;
    }

    private URI buildInternal(Map values)
        throws IllegalArgumentException, UriBuilderException {
        if (logger.isTraceEnabled()) {
            logger.trace("buildInternal({}) entry", values //$NON-NLS-1$
                );
        }
        StringBuilder out = new StringBuilder();
        buildScheme(values, out);
        buildAuthority(values, out);
        buildPath(values, out);
        buildQuery(values, out);
        buildFragment(values, out);
        String uriString = out.toString();
        try {
            logger.trace("buildInternal() exit", uriString); //$NON-NLS-1$
            return new URI(uriString);
        } catch (URISyntaxException e) {
            throw new UriBuilderException(e);
        }
    }

    private void buildScheme(Map values, StringBuilder out) {
        logger.trace("buildScheme({}, {}) entry", values, out); //$NON-NLS-1$
        if (scheme == null) {
            logger.trace("buildScheme() is null so returning"); //$NON-NLS-1$
            return;
        }
        JaxRsUriTemplateProcessor.expand(scheme,
                                         MultivaluedMapImpl.toMultivaluedMapString(values),
                                         out);
        out.append(':');
        logger.trace("buildScheme() exit changed out to {}", out); //$NON-NLS-1$
    }

    private void buildAuthority(Map values, StringBuilder out) {
        logger.trace("buildAuthority({}, {}) entry", values, out); //$NON-NLS-1$
        if (userInfo == null && host == null && port == -1) {
            logger.trace("buildAuthority() is null so returning"); //$NON-NLS-1$
            return;
        }
        out.append("//"); //$NON-NLS-1$
        if (userInfo != null) {
            String eUserInfo =
                JaxRsUriTemplateProcessor.expand(userInfo, MultivaluedMapImpl
                    .toMultivaluedMapString(values));
            eUserInfo = UriEncoder.encodeUserInfo(eUserInfo, true);
            out.append(eUserInfo);
            out.append('@');
        }
        if (host != null) {
            JaxRsUriTemplateProcessor.expand(host, MultivaluedMapImpl
                .toMultivaluedMapString(values), out);
        }
        if (port != -1) {
            out.append(':');
            out.append(port);
        }
        logger.trace("buildAuthority() exit changed out to {}", out); //$NON-NLS-1$
    }

    private void buildPath(Map values, StringBuilder out) {
        if (logger.isTraceEnabled()) {
            logger.trace("buildPath({}, {}) entry", new Object[] {values, out //$NON-NLS-1$
            });
        }
        if (segments == null || segments.size() == 0) {
            logger.trace("buildPath() segments is null or empty so returning"); //$NON-NLS-1$
            return;
        }

        boolean first = true;
        for (PathSegment segment : segments) {
            // segment
            String segmentPath = segment.getPath();
            String eSegmentPath =
                JaxRsUriTemplateProcessor.expand(segmentPath, MultivaluedMapImpl
                    .toMultivaluedMapString(values));
            // note that even though we're encoding inside a loop over segments,
            // we're treating the path string (eSegmentPath) as just a path (so
            // "/" will not be encoded).

            // this allows the "values" map to contain values with "/" which
            // should not be encoded (since "/" is an unreserved character in
            // paths but not path segments). for real path segments specified by
            // the segments() method, the "/" is encoded in that method
            eSegmentPath = UriEncoder.encodePath(eSegmentPath, true);

            // we output the path separator if:
            // 1. if we already have some uri built and the last character is
            // not the path separator
            // 2. if the uri is still empty and this is not the first path
            // segment
            if ((out.length() > 0 && out.charAt(out.length() - 1) != '/') || (out.length() == 0 && !first)) {
                out.append('/');
            }
            first = false;

            // output the path segment
            out.append(eSegmentPath);

            // matrix parameters
            MultivaluedMap matrixParameters = segment.getMatrixParameters();
            for (String matrix : matrixParameters.keySet()) {
                // matrix parameter
                String eMatrix =
                    JaxRsUriTemplateProcessor.expand(matrix, MultivaluedMapImpl
                        .toMultivaluedMapString(values));
                eMatrix = UriEncoder.encodeMatrix(eMatrix, true);

                // matrix values
                for (String matrixValue : matrixParameters.get(matrix)) {
                    String eValue =
                        JaxRsUriTemplateProcessor.expand(matrixValue, MultivaluedMapImpl
                            .toMultivaluedMapString(values));
                    eValue = UriEncoder.encodeMatrix(eValue, true);
                    out.append(';');
                    out.append(eMatrix);
                    out.append('=');
                    out.append(eValue);
                }
            }
        }
        if (logger.isTraceEnabled()) {
            logger.trace("buildPath() exit changes out to {} ", out); //$NON-NLS-1$
        }
    }

    private void buildQuery(Map values, StringBuilder out) {
        if (logger.isTraceEnabled()) {
            logger.trace("buildQuery({}, {}) entry", values, out); //$NON-NLS-1$
        }
        if (query == null || query.size() == 0) {
            logger.trace("buildQuery() exit - query is null"); //$NON-NLS-1$
            return;
        }
        char delim = '?';
        for (String queryParam : query.keySet()) {
            // query param name
            String eQueryParam =
                JaxRsUriTemplateProcessor.expand(queryParam, MultivaluedMapImpl
                    .toMultivaluedMapString(values));
            eQueryParam = UriEncoder.encodeQueryParam(eQueryParam, true);

            // query param values
            for (String queryValue : query.get(queryParam)) {
                String eQueryValue =
                    JaxRsUriTemplateProcessor.expand(queryValue, MultivaluedMapImpl
                        .toMultivaluedMapString(values));
                eQueryValue = UriEncoder.encodeQueryParam(eQueryValue, true);
                out.append(delim);
                out.append(eQueryParam);
                delim = '&';
                if (eQueryValue == null) {
                    continue;
                }
                out.append('=');
                out.append(eQueryValue);
            }
        }
        logger.trace("buildQuery() exit - changes out to {}", out); //$NON-NLS-1$
    }

    private void buildFragment(Map values, StringBuilder out) {
        logger.trace("buildFragment({}, {})", values, out); //$NON-NLS-1$
        if (fragment == null) {
            return;
        }
        String eFragment =
            JaxRsUriTemplateProcessor.expand(fragment, MultivaluedMapImpl
                .toMultivaluedMapString(values));
        eFragment = UriEncoder.encodeFragment(eFragment, true);
        out.append('#');
        out.append(eFragment);
        logger.trace("buildFragment() exit - changes out to {}", out); //$NON-NLS-1$
    }

    @Override
    public URI build(Object... values) throws IllegalArgumentException, UriBuilderException {
        return build(true, values);
    }

    @Override
    public URI buildFromEncoded(Object... values) throws IllegalArgumentException,
        UriBuilderException {
        return build(false, values);
    }

    private URI build(boolean escapePercent, Object... values) throws IllegalArgumentException,
        UriBuilderException {
        if (logger.isTraceEnabled()) {
            logger.trace("build({}, {}) enFtry", Boolean.valueOf(escapePercent), Arrays //$NON-NLS-1$
                .asList(values));
        }
        if (schemeSpecificPart != null) {
            try {
                // uri templates will be automatically encoded
                URI uri = new URI(scheme, schemeSpecificPart, fragment);
                if (logger.isTraceEnabled()) {
                    logger.trace("build() returning {}", uri.toString()); //$NON-NLS-1$
                }
                return uri;
            } catch (URISyntaxException e) {
                throw new IllegalArgumentException(Messages
                    .getMessage("isInvalid", "schemeSpecificPart", schemeSpecificPart), e); //$NON-NLS-1$ //$NON-NLS-2$
            }
        }

        Set names = getVariableNamesList();
        if (values == null || names.size() > values.length) {
            throw new IllegalArgumentException(Messages.getMessage("missingVariable", "values")); //$NON-NLS-1$ //$NON-NLS-2$
        }
        Map valuesMap = new HashMap();
        int i = 0;
        for (String name : names) {
            if (values[i] == null) {
                throw new IllegalArgumentException(Messages.getMessage("variableIsNull", name)); //$NON-NLS-1$
            }
            // put only the first occurrence of the value in the map
            if (valuesMap.get(name) == null) {
                String value = values[i].toString();
                if (escapePercent) {
                    value = escapePercent(value);
                }
                valuesMap.put(name, value);
                logger.trace("name: {} has value : {}", name, value); //$NON-NLS-1$
            }
            ++i;
        }
        for (; i < values.length; ++i) {
            if (values[i] == null) {
                throw new IllegalArgumentException(Messages
                    .getMessage("valueAtIndexIsNull", String.valueOf(i))); //$NON-NLS-1$
            }
        }
        return buildInternal(valuesMap);
    }

    @Override
    public URI buildFromMap(Map values) throws IllegalArgumentException,
        UriBuilderException {
        return buildFromMap(true, values);
    }

    @Override
    public URI buildFromEncodedMap(Map values)
        throws IllegalArgumentException, UriBuilderException {
        return buildFromMap(false, values);
    }

    private URI buildFromMap(boolean escapePercent, Map values)
        throws IllegalArgumentException, UriBuilderException {
        if (logger.isTraceEnabled()) {
            logger.trace("buildFromMap({}, {})", Boolean.valueOf(escapePercent), values); //$NON-NLS-1$
        }
        Set names = getVariableNamesList();
        if (values == null || (names.size() > values.size())) {
            throw new IllegalArgumentException(Messages.getMessage("missingVariable", "values")); //$NON-NLS-1$ //$NON-NLS-2$
        }
        logger.trace("names are {}", names); //$NON-NLS-1$
        Map valuesMap = new HashMap();
        for (String name : names) {
            Object value = values.get(name);
            if (value == null) {
                throw new IllegalArgumentException(Messages.getMessage("variableIsNull", name)); //$NON-NLS-1$
            }
            // put only the first occurrence of the value in the map
            if (valuesMap.get(name) == null) {
                String valueToPut = value.toString();
                if (escapePercent) {
                    valueToPut = escapePercent(valueToPut);
                }
                valuesMap.put(name, valueToPut);
                logger.trace("name {} set to value {}", name, valueToPut); //$NON-NLS-1$
            }
        }
        return buildInternal(valuesMap);
    }

    private String escapePercent(String string) {
        logger.trace("escapePercent({}) entry", string); //$NON-NLS-1$
        StringBuilder out = new StringBuilder(string.length());
        for (int i = 0; i < string.length(); ++i) {
            char c = string.charAt(i);
            if (c == '%') {
                out.append("%25"); //$NON-NLS-1$
            } else {
                out.append(c);
            }
        }
        String ret = out.toString();
        logger.trace("escapePercent() return {}", ret); //$NON-NLS-1$
        return ret;
    }

    @Override
    public UriBuilder clone() {
        logger.trace("clone() entry"); //$NON-NLS-1$
        UriBuilderImpl uriBuilder = new UriBuilderImpl();
        uriBuilder.scheme(this.scheme);
        uriBuilder.userInfo(this.userInfo);
        uriBuilder.host(this.host);
        uriBuilder.port(this.port);
        uriBuilder.fragment(this.fragment);
        uriBuilder.segments(this.segments);
        uriBuilder.query(this.query);
        logger.trace("clone() exit returning {}", uriBuilder); //$NON-NLS-1$
        return uriBuilder;
    }

    private void query(MultivaluedMap query) {
        logger.trace("query({}) entry", query); //$NON-NLS-1$
        if (query == null) {
            logger.trace("query exit"); //$NON-NLS-1$
            return;
        }
        this.query = ((MultivaluedMapImpl)query).clone();
        logger.trace("query exit"); //$NON-NLS-1$
    }

    private void segments(List pathSegments) {
        logger.trace("segments({}) entry", pathSegments); //$NON-NLS-1$
        if (pathSegments == null) {
            logger.trace("segments() exit"); //$NON-NLS-1$
            return;
        }
        this.segments = new ArrayList();
        for (PathSegment segment : pathSegments) {
            this.segments.add(((PathSegmentImpl)segment).clone());
        }
        logger.trace("segments() exit"); //$NON-NLS-1$
    }

    @Override
    public UriBuilder fragment(String fragment) {
        logger.trace("fragment({}) entry", fragment); //$NON-NLS-1$
        this.fragment = fragment;
        logger.trace("fragment() exit"); //$NON-NLS-1$
        return this;
    }

    @Override
    public UriBuilder host(String host) throws IllegalArgumentException {
        logger.trace("host({}) entry", host); //$NON-NLS-1$
        if ("".equals(host)) { //$NON-NLS-1$
            throw new IllegalArgumentException(Messages.getMessage("variableIsEmpty", "host")); //$NON-NLS-1$ //$NON-NLS-2$
        }
        this.host = host;
        logger.trace("host() exit"); //$NON-NLS-1$
        return this;
    }

    @Override
    public UriBuilder matrixParam(String name, Object... values) throws IllegalArgumentException {
        if (logger.isTraceEnabled()) {
            logger.trace("matrixParam({}, {}) entry", name, (values == null) ? null : Arrays //$NON-NLS-1$
                .asList(values));
        }
        if (name == null) {
            throw new IllegalArgumentException(Messages.getMessage("variableIsNull", "name")); //$NON-NLS-1$ //$NON-NLS-2$
        }
        if (values == null) {
            throw new IllegalArgumentException(Messages.getMessage("variableIsNull", "values")); //$NON-NLS-1$ //$NON-NLS-2$
        }
        PathSegmentImpl lastSegment = getLastPathSegment();
        for (Object value : values) {
            lastSegment.getMatrixParameters().add(name, value.toString());
            if (logger.isTraceEnabled()) {
                logger.trace("lastSegment add({}, {})", name, value.toString()); //$NON-NLS-1$
            }
        }
        logger.trace("matrixParam exit"); //$NON-NLS-1$
        return this;
    }

    private PathSegmentImpl getLastPathSegment() {
        logger.trace("getLastPathSegment() entry"); //$NON-NLS-1$
        List pathSegments = getPathSegments();
        logger.trace("getPathSegments() is {}", pathSegments); //$NON-NLS-1$
        PathSegmentImpl lastSegment = null;
        int lastSegmentIndex = pathSegments.size() - 1;
        if (lastSegmentIndex >= 0) {
            lastSegment = (PathSegmentImpl)pathSegments.get(lastSegmentIndex);
        } else {
            lastSegment = new PathSegmentImpl(""); //$NON-NLS-1$
            pathSegments.add(lastSegment);
        }
        logger.trace("getLastPathSegment() returning {}", lastSegment); //$NON-NLS-1$
        return lastSegment;
    }

    @Override
    public UriBuilder path(String path) throws IllegalArgumentException {
        logger.trace("path({}) entry", path); //$NON-NLS-1$
        if (path == null) {
            throw new IllegalArgumentException(Messages.getMessage("variableIsNull", "path")); //$NON-NLS-1$ //$NON-NLS-2$
        }
        if ("".equals(path)) { //$NON-NLS-1$
            // do nothing if there is an empty path
            return this;
        }

        if (isFirstCall) {
            isFirstCall = false;
            if (path.indexOf(":") != -1) { //$NON-NLS-1$
                // we need to parse this as scheme:scheme-specific-part#fragment
                // for
                // a hierarchical URI
                // if a non-valid URI is passed in, the path is parsed as normal
                String[] segments = path.split(":", 2); //$NON-NLS-1$
                if (segments.length == 2 && segments[0].length() > 0 && segments[0].indexOf("{") == -1) { //$NON-NLS-1$
                    String scheme = segments[0];
                    segments = segments[1].split("#", 2); //$NON-NLS-1$
                    if (segments[0].length() > 0) {
                        String schemeSpecificPart = segments[0];
                        String fragment = null;
                        if (segments.length == 2)
                            fragment = segments[1];
                        scheme(scheme);
                        schemeSpecificPart(schemeSpecificPart);
                        fragment(fragment);
                        logger.trace("replacePath() exit"); //$NON-NLS-1$
                        return this;
                    }
                }
            }
        }

        // strip off the authority prefix if present
        String _path = path;
        if (path.startsWith("//")) { //$NON-NLS-1$
            if (path.length() > 2) {
                _path = path.substring(2);
                getPathSegments().add(new PathSegmentImpl("/")); //$NON-NLS-1$
            } else {
                logger.trace("path() exit"); //$NON-NLS-1$
                return this;
            }
        }

        List list = UriHelper.parsePath(_path);
        logger.trace("path is {}", list); //$NON-NLS-1$
        for (PathSegment segment : list) {
            segment(segment.getPath());
            MultivaluedMap matrixParameters = segment.getMatrixParameters();
            for (String matrix : matrixParameters.keySet()) {
                matrixParam(matrix, matrixParameters.get(matrix).toArray());
            }
        }
        logger.trace("path() exit"); //$NON-NLS-1$
        return this;
    }

    @SuppressWarnings("unchecked")
    @Override
    public UriBuilder path(Class resource) throws IllegalArgumentException {
        logger.trace("path({}) entry", resource); //$NON-NLS-1$
        if (resource == null) {
            throw new IllegalArgumentException(Messages.getMessage("variableIsNull", "resource")); //$NON-NLS-1$ //$NON-NLS-2$
        }
        isFirstCall = false;
        Path pathAnnotation = ((Class)resource).getAnnotation(Path.class);
        if (pathAnnotation == null) {
            throw new IllegalArgumentException(Messages.getMessage("resourceNotAnnotated", "@javax.ws.rs.Path", resource)); //$NON-NLS-1$ //$NON-NLS-2$
        }
        String path = pathAnnotation.value();
        logger.trace("path annotation value is {}", path); //$NON-NLS-1$
        path(path);
        logger.trace("path() exit"); //$NON-NLS-1$
        return this;
    }

    @Override
    public UriBuilder path(Method method) throws IllegalArgumentException {
        logger.trace("path({}) entry", method); //$NON-NLS-1$
        if (method == null) {
            throw new IllegalArgumentException(Messages.getMessage("variableIsNull", "method")); //$NON-NLS-1$ //$NON-NLS-2$
        }
        Path pathAnnotation = method.getAnnotation(Path.class);
        if (pathAnnotation == null) {
            throw new IllegalArgumentException(Messages.getMessage("methodNotAnnotated", "@javax.ws.rs.Path", method)); //$NON-NLS-1$ //$NON-NLS-2$
        }
        String path = pathAnnotation.value();
        logger.trace("path method annotation is {}", path); //$NON-NLS-1$
        path(path);
        logger.trace("path() exit"); //$NON-NLS-1$
        return this;
    }

    @SuppressWarnings("unchecked")
    @Override
    public UriBuilder path(Class resource, String method) throws IllegalArgumentException {
        logger.trace("path({}, {}) entry", resource, method); //$NON-NLS-1$
        if (resource == null) {
            throw new IllegalArgumentException(Messages.getMessage("variableIsNull", "resource")); //$NON-NLS-1$ //$NON-NLS-2$
        }
        if (method == null) {
            throw new IllegalArgumentException(Messages.getMessage("variableIsNull", "method")); //$NON-NLS-1$ //$NON-NLS-2$
        }

        Method foundMethod = null;
        Method[] methods = resource.getDeclaredMethods();
        for (Method m : methods) {
            if (m.getName().equals(method)) {
                Path pathAnnotation = m.getAnnotation(Path.class);
                if (pathAnnotation != null) {
                    if (foundMethod != null) {
                        throw new IllegalArgumentException(Messages
                            .getMessage("moreThanOneMethodAnnotated", "@javax.ws.rs.Path", method, resource)); //$NON-NLS-1$ //$NON-NLS-2$
                    }
                    foundMethod = m;
                }
            }
        }
        if (foundMethod == null) {
            throw new IllegalArgumentException(Messages.getMessage("noMethodAnnotated", "@javax.ws.rs.Path", method, resource)); //$NON-NLS-1$ //$NON-NLS-2$
        }
        path(foundMethod);
        logger.trace("path() exit"); //$NON-NLS-1$
        return this;
    }

    @Override
    public UriBuilder port(int port) throws IllegalArgumentException {
        if (logger.isTraceEnabled()) {
            logger.trace("port({}) entry", port); //$NON-NLS-1$
        }
        if (port < -1) {
            throw new IllegalArgumentException(Messages.getMessage("invalidPort", String.valueOf(port))); //$NON-NLS-1$
        }
        this.port = port;
        logger.trace("port() exit"); //$NON-NLS-1$
        return this;
    }

    @Override
    public UriBuilder queryParam(String name, Object... values) throws IllegalArgumentException {
        if (logger.isTraceEnabled()) {
            logger.trace("queryParam({}, {}) entry", name, (values == null) ? null : Arrays //$NON-NLS-1$
                .asList(values));
        }
        if (name == null) {
            throw new IllegalArgumentException(Messages.getMessage("variableIsNull", "name")); //$NON-NLS-1$ //$NON-NLS-2$
        }
        if (values == null) {
            throw new IllegalArgumentException(Messages.getMessage("variableIsNull", "values")); //$NON-NLS-1$ //$NON-NLS-2$
        }
        MultivaluedMap query = getQuery();
        logger.trace("query map is {}", query); //$NON-NLS-1$
        for (Object value : values) {
            if (value == null) {
                throw new IllegalArgumentException(Messages.getMessage("variableIsNull", "value")); //$NON-NLS-1$ //$NON-NLS-2$
            }
            query.add(name, value != null ? value.toString() : null);
        }
        logger.trace("queryParam() exit"); //$NON-NLS-1$
        return this;
    }

    @Override
    public UriBuilder replaceMatrix(String matrix) throws IllegalArgumentException {
        logger.trace("replaceMatrix({}) entry", matrix); //$NON-NLS-1$
        // clear all matrix parameters from existing last segment
        PathSegmentImpl lastPathSegment = getLastPathSegment();
        lastPathSegment.clearAllMatrixParameters();

        // use a temporary PathSegmentImpl to parse the matrix parameters
        PathSegmentImpl tmpPathSegment = new PathSegmentImpl("", matrix); //$NON-NLS-1$
        MultivaluedMap matrixParameters = tmpPathSegment.getMatrixParameters();
        for (String param : matrixParameters.keySet()) {
            List matrixValues = matrixParameters.get(param);
            // add the matrix parameter and its values
            matrixParam(param, matrixValues.toArray());
        }
        logger.trace("replaceMatrix() exit"); //$NON-NLS-1$
        return this;
    }

    @Override
    public UriBuilder replaceMatrixParam(String name, Object... values)
        throws IllegalArgumentException {
        if (logger.isTraceEnabled()) {
            logger.trace("replaceMatrixParam({}, {})", name, (values == null) ? null : Arrays //$NON-NLS-1$
                .asList(values));
        }
        if (name == null) {
            throw new IllegalArgumentException(Messages.getMessage("variableIsNull", "name")); //$NON-NLS-1$ //$NON-NLS-2$
        }
        PathSegmentImpl lastPathSegment = getLastPathSegment();
        if (values == null || values.length == 0) {
            lastPathSegment.clearMatrixParameter(name);
        } else {
            List valuesList = lastPathSegment.getMatrixParameters().get(name);
            if (valuesList != null) {
                valuesList.clear();
            }
            matrixParam(name, values);
        }
        logger.trace("replaceMatrixParam() exit"); //$NON-NLS-1$
        return this;
    }

    @Override
    public UriBuilder replacePath(String path) {
        logger.trace("replacePath({}) entry", path); //$NON-NLS-1$
        if (isFirstCall) {
            isFirstCall = false;
            if (path == null) {
                throw new IllegalArgumentException(Messages.getMessage("variableIsNull", "path")); //$NON-NLS-1$ //$NON-NLS-2$
            }
        }
        if (path == null) {
            logger.trace("path is null. resetting"); //$NON-NLS-1$
            reset();
            logger.trace("replacePath() exit"); //$NON-NLS-1$
            return this;
        }
        getPathSegments().clear();
        if (path.indexOf(":") != -1) { //$NON-NLS-1$
            // we need to parse this as scheme:scheme-specific-part#fragment for
            // a hierarchical URI
            // if a non-valid URI is passed in, the path is parsed as normal
            String[] segments = path.split(":", 2); //$NON-NLS-1$
            if (segments.length == 2 && segments[0].length() > 0 && segments[0].indexOf("{") == -1) { //$NON-NLS-1$
                String scheme = segments[0];
                segments = segments[1].split("#", 2); //$NON-NLS-1$
                if (segments[0].length() > 0) {
                    String schemeSpecificPart = segments[0];
                    String fragment = null;
                    if (segments.length == 2)
                        fragment = segments[1];
                    scheme(scheme);
                    schemeSpecificPart(schemeSpecificPart);
                    fragment(fragment);
                    logger.trace("replacePath() exit"); //$NON-NLS-1$
                    return this;
                }
            }
        }
        if (path != null && !"".equals(path)) { //$NON-NLS-1$
            path(path);
        }
        logger.trace("replacePath() exit"); //$NON-NLS-1$
        return this;
    }

    @Override
    public UriBuilder replaceQuery(String query) throws IllegalArgumentException {
        logger.trace("replaceQuery({}) entry", query); //$NON-NLS-1$
        getQuery().clear();
        if (query != null) {
            query = query.replaceAll(" ", "%20"); //$NON-NLS-1$ //$NON-NLS-2$
            MultivaluedMap queries = UriHelper.parseQuery(query);
            // should values be URL encoded or query encoded?

            logger.trace("queries after parsing: {}", queries); //$NON-NLS-1$
            MultivaluedMap queryValues = getQuery();
            for (String name : queries.keySet()) {
                List values = queries.get(name);
                for (String v : values) {
                    if (v == null) {
                        queryValues.add(name, null);
                    } else {
                        queryParam(name, v);
                    }
                }
            }
        }
        logger.trace("replaceQuery() exit"); //$NON-NLS-1$
        return this;
    }

    @Override
    public UriBuilder replaceQueryParam(String name, Object... values)
        throws IllegalArgumentException {
        if (logger.isTraceEnabled()) {
            logger.trace("replaceQueryParam({}, {}) entry", name, (values == null) ? null : Arrays //$NON-NLS-1$
                .asList(values));
        }
        if (name == null) {
            throw new IllegalArgumentException(Messages.getMessage("variableIsNull", "name")); //$NON-NLS-1$ //$NON-NLS-2$
        }
        // remove any exiting values
        getQuery().remove(name);

        if (values != null) {
            queryParam(name, values);
        }
        logger.trace("replaceQueryParam() exit"); //$NON-NLS-1$
        return this;
    }

    @Override
    public UriBuilder scheme(String scheme) throws IllegalArgumentException {
        logger.trace("scheme({}) entry", scheme); //$NON-NLS-1$
        this.scheme = scheme;
        logger.trace("scheme() exit"); //$NON-NLS-1$
        return this;
    }

    @Override
    public UriBuilder schemeSpecificPart(String ssp) throws IllegalArgumentException {
        logger.trace("schemeSpecificPart({}) entry", ssp); //$NON-NLS-1$
        if (ssp == null) {
            throw new IllegalArgumentException(Messages.getMessage("variableIsNull", "ssp")); //$NON-NLS-1$ //$NON-NLS-2$
        }

        if (!ssp.startsWith("/")) { //$NON-NLS-1$
            // An opaque URI is an absolute URI whose scheme-specific part does
            // not begin with a slash character ('/').
            // Opaque URIs are not subject to further parsing.
            schemeSpecificPart = ssp;
            return this;
        }

        URI uri = null;
        try {
            // uri templates will be automatically encoded
            uri = new URI(scheme, ssp, fragment);
        } catch (URISyntaxException e) {
            throw new IllegalArgumentException(Messages
                .getMessage("isInvalid", "schemeSpecificPart", schemeSpecificPart), e); //$NON-NLS-1$ //$NON-NLS-2$
        }

        resetSchemeSpecificPart();

        // decode every part before applying
        if (uri.getRawUserInfo() != null) {
            userInfo(UriEncoder.decodeString(uri.getRawUserInfo()));
        }
        if (uri.getHost() != null) {
            host(UriEncoder.decodeString(uri.getHost()));
        }
        if (uri.getPort() != -1) {
            port(uri.getPort());
        }
        if (uri.getRawPath() != null) {
            String path = uri.getRawPath();
            if(this.host == null && uri.getRawAuthority() != null)
                path = UriEncoder.decodeString(uri.getRawAuthority()) + "/" + path; //$NON-NLS-1$
            path(UriEncoder.decodeString(path));
        }
        logger.trace("schemeSpecificPart() exit"); //$NON-NLS-1$
        return this;
    }

    @Override
    public UriBuilder segment(String... segments) throws IllegalArgumentException {
        if (logger.isTraceEnabled()) {
            logger.trace("segment({}) entry", (segments == null) ? null : Arrays.asList(segments)); //$NON-NLS-1$
        }
        if (segments == null) {
            throw new IllegalArgumentException(Messages.getMessage("variableIsNull", "segments")); //$NON-NLS-1$ //$NON-NLS-2$
        }

        List pathSegments = getPathSegments();
        for (int i = 0; i < segments.length; ++i) {
            if (segments[i] == null) {
                throw new IllegalArgumentException(Messages
                    .getMessage("segmentAtIndexIsNull", String.valueOf(i))); //$NON-NLS-1$
            }
            if (segments[i].contains("/")) { //$NON-NLS-1$
                String segValue = segments[i].replace("/", "%2F"); //$NON-NLS-1$ //$NON-NLS-2$
                pathSegments.add(new PathSegmentImpl(segValue));
            } else {
                pathSegments.add(new PathSegmentImpl(segments[i]));
            }
        }
        logger.trace("segment() exit"); //$NON-NLS-1$
        return this;
    }

    @Override
    public UriBuilder userInfo(String ui) {
        logger.trace("userInfo({}) entry", ui); //$NON-NLS-1$
        userInfo = ui;
        logger.trace("userInfo() exit"); //$NON-NLS-1$
        return this;
    }

    @Override
    public UriBuilder uri(URI uri) throws IllegalArgumentException {
        logger.trace("Entering uri({})", uri); //$NON-NLS-1$
        if (uri == null) {
            throw new IllegalArgumentException(Messages.getMessage("variableIsNull", "uri")); //$NON-NLS-1$ //$NON-NLS-2$
        }

        isFirstCall = false;

        if (uri.getScheme() != null) {
            logger.trace("Constructing scheme"); //$NON-NLS-1$
            scheme(uri.getScheme());
        }
        if (uri.getRawUserInfo() != null) {
            logger.trace("Constructing userInfo"); //$NON-NLS-1$
            userInfo(uri.getRawUserInfo());
        }
        if (uri.getHost() != null) {
            logger.trace("Constructing host"); //$NON-NLS-1$
            host(uri.getHost());
        }
        if (uri.getPort() != -1) {
            logger.trace("Constructing port"); //$NON-NLS-1$
            port(uri.getPort());
        }
        if (uri.getRawPath() != null) {
            logger.trace("Constructing rawPath"); //$NON-NLS-1$
            path(uri.getRawPath());
        }
        if (uri.getRawQuery() != null) {
            logger.trace("Constructing rawQuery"); //$NON-NLS-1$
            replaceQuery(uri.getRawQuery());
        }
        if (uri.getRawFragment() != null) {
            logger.trace("Constructing fragment"); //$NON-NLS-1$
            fragment(uri.getRawFragment());
        }
        if (uri.getRawSchemeSpecificPart() != null) {
            logger.trace("Constructing schemeSpecificPart"); //$NON-NLS-1$
            schemeSpecificPart(uri.getRawSchemeSpecificPart());
        }
        logger.trace("uri() exit"); //$NON-NLS-1$
        return this;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy