Example usage for java.util.regex Matcher groupCount

List of usage examples for java.util.regex Matcher groupCount

Introduction

In this page you can find the example usage for java.util.regex Matcher groupCount.

Prototype

public int groupCount() 

Source Link

Document

Returns the number of capturing groups in this matcher's pattern.

Usage

From source file:org.grails.datastore.gorm.finders.DynamicFinder.java

public DynamicFinderInvocation createFinderInvocation(Class clazz, String methodName,
        Closure additionalCriteria, Object[] arguments) {

    List expressions = new ArrayList();
    if (arguments == null)
        arguments = EMPTY_OBJECT_ARRAY;//from  w  w  w  .ja va  2  s  .c  o  m
    else {
        Object[] tmp = new Object[arguments.length];
        System.arraycopy(arguments, 0, tmp, 0, arguments.length);
        arguments = tmp;
    }
    Matcher match = pattern.matcher(methodName);
    // find match
    match.find();

    String[] queryParameters;
    int totalRequiredArguments = 0;
    // get the sequence clauses
    final String querySequence;
    int groupCount = match.groupCount();
    if (groupCount == 6) {
        String booleanProperty = match.group(3);
        if (booleanProperty == null) {
            booleanProperty = match.group(6);
            querySequence = null;
        } else {
            querySequence = match.group(5);
        }
        Boolean arg = Boolean.TRUE;
        if (booleanProperty.matches("Not[A-Z].*")) {
            booleanProperty = booleanProperty.substring(3);
            arg = Boolean.FALSE;
        }
        MethodExpression booleanExpression = findMethodExpression(clazz, booleanProperty);
        booleanExpression.setArguments(new Object[] { arg });
        expressions.add(booleanExpression);
    } else {
        querySequence = match.group(2);
    }
    // if it contains operator and split
    boolean containsOperator = false;
    String operatorInUse = null;
    if (querySequence != null) {
        for (int i = 0; i < operators.length; i++) {
            Matcher currentMatcher = operatorPatterns[i].matcher(querySequence);
            if (currentMatcher.find()) {
                containsOperator = true;
                operatorInUse = operators[i];

                queryParameters = querySequence.split(operatorInUse);

                // loop through query parameters and create expressions
                // calculating the number of arguments required for the expression
                int argumentCursor = 0;
                for (String queryParameter : queryParameters) {
                    MethodExpression currentExpression = findMethodExpression(clazz, queryParameter);
                    final int requiredArgs = currentExpression.getArgumentsRequired();
                    // populate the arguments into the GrailsExpression from the argument list
                    Object[] currentArguments = new Object[requiredArgs];
                    if ((argumentCursor + requiredArgs) > arguments.length) {
                        throw new MissingMethodException(methodName, clazz, arguments);
                    }

                    for (int k = 0; k < requiredArgs; k++, argumentCursor++) {
                        currentArguments[k] = arguments[argumentCursor];
                    }
                    currentExpression = getInitializedExpression(currentExpression, currentArguments);
                    PersistentEntity persistentEntity = datastore.getMappingContext()
                            .getPersistentEntity(clazz.getName());

                    try {
                        currentExpression.convertArguments(persistentEntity);
                    } catch (ConversionException e) {
                        throw new MissingMethodException(methodName, clazz, arguments);
                    }

                    // add to list of expressions
                    totalRequiredArguments += currentExpression.argumentsRequired;
                    expressions.add(currentExpression);
                }
                break;
            }
        }
    }
    // otherwise there is only one expression
    if (!containsOperator && querySequence != null) {
        MethodExpression solo = findMethodExpression(clazz, querySequence);

        final int requiredArguments = solo.getArgumentsRequired();
        if (requiredArguments > arguments.length) {
            throw new MissingMethodException(methodName, clazz, arguments);
        }

        totalRequiredArguments += requiredArguments;
        Object[] soloArgs = new Object[requiredArguments];
        System.arraycopy(arguments, 0, soloArgs, 0, requiredArguments);
        solo = getInitializedExpression(solo, arguments);
        PersistentEntity persistentEntity = datastore.getMappingContext().getPersistentEntity(clazz.getName());
        try {
            solo.convertArguments(persistentEntity);
        } catch (ConversionException e) {
            if (!(persistentEntity.getPropertyByName(solo.propertyName) instanceof Basic)) {
                throw new MissingMethodException(methodName, clazz, arguments);
            }
        }
        expressions.add(solo);
    }

    // if the total of all the arguments necessary does not equal the number of arguments
    // throw exception
    if (totalRequiredArguments > arguments.length) {
        throw new MissingMethodException(methodName, clazz, arguments);
    }

    // calculate the remaining arguments
    Object[] remainingArguments = new Object[arguments.length - totalRequiredArguments];
    if (remainingArguments.length > 0) {
        for (int i = 0, j = totalRequiredArguments; i < remainingArguments.length; i++, j++) {
            remainingArguments[i] = arguments[j];
        }
    }

    return new DynamicFinderInvocation(clazz, methodName, remainingArguments, expressions, additionalCriteria,
            operatorInUse);
}

From source file:ca.queensu.cs.sail.mailboxmina2.main.modules.ThreadsModule.java

/**
 * This heuristic creates associations based on the subject and a time
 * window Default Time window is 1 month
 *//*from  ww  w  .  jav a2  s  .  c om*/
private void heuristicSubject(List<MM2Message> messages, Connection connection) {

    // This is the msg_id ==> Date
    Hashtable<String, Date> msg_id_to_date = new Hashtable<String, Date>();

    // This is (original) subject ==> msg_id
    Hashtable<String, String> subject_to_msg_id = new Hashtable<String, String>();

    // This is msg_id ==> (processed) subject
    Hashtable<String, String> msg_id_to_subject = new Hashtable<String, String>();

    // This is child ==> parent
    Hashtable<String, String> msg_id_to_msg_id = new Hashtable<String, String>();

    // Capture the most commong reply patterns
    // Fw: Re: Aw: Wg: 
    Pattern reply_pattern = Pattern.compile(
            "^(\\[.*?\\] )?(([rR][eE]:)|([aA][wW]:)|([fF][wW]:)|([wW][gG]:)|([fF][wW][dD]:)|([wW][tT][rR]:)|([aA]ntwort:))(.*?)$");

    try {
        for (MM2Message msg : messages) {
            String msg_id = msg.getHeaderEntry("msg_id");
            msg_id_to_date.put(msg_id, msg.getMsg_date());
            // We assume the subject to be at least ""
            String raw_subject = msg.getSubject();
            // Determine whether the subject describes a reply or an original posting
            Matcher matcher = reply_pattern.matcher(raw_subject);
            if (matcher.matches()) {
                String stripped_subject = matcher.group(matcher.groupCount());
                Main.getLogger().debug(5, this,
                        "I think message is a reply and the original subject is: " + stripped_subject.trim());
                // Store the information in the forward table
                msg_id_to_subject.put(msg_id, stripped_subject.trim());
            } else {
                // We think that this is not a reply - hence it must be an original posting ;-)
                subject_to_msg_id.put(raw_subject, msg_id);
                Main.getLogger().debug(5, this,
                        "I think message is an original posting: " + raw_subject.trim());
            }
        }

        // Now we need to find parent relations by subject.
        // Still we will apply a sliding window approach using a given offset
        // to make sure, we don't capture events of people re-using old subject names

        for (String child_msg_id : msg_id_to_subject.keySet()) {
            String origSubj = msg_id_to_subject.get(child_msg_id);
            String parent_msg_id = subject_to_msg_id.get(origSubj);
            // If we found an entry in the table
            if (parent_msg_id != null) {
                // Check if the potential parent is (OFFSET) older than child
                Date d1 = msg_id_to_date.get(parent_msg_id);
                Date d2 = DateUtils.addMonths(msg_id_to_date.get(child_msg_id), OFFSET);
                if (d1.compareTo(d2) >= 0) {
                    Main.getLogger().debug(5, this,
                            "I know that message " + child_msg_id + " has the parent " + parent_msg_id);
                    msg_id_to_msg_id.put(child_msg_id, parent_msg_id);
                }
            }
        }

        Main.getLogger().debug(5, "original posting subjects resolved = " + subject_to_msg_id.size());
        Main.getLogger().debug(5, "subjects resolved replys = " + msg_id_to_subject.size());

        // Store the parents and roots into the database
        Main.getLogger().log("The heuristic could resolve " + msg_id_to_msg_id.size() + " parent relations!");
        Main.getLogger().log("Storing associations found by in-reply-to heuristic in the database...");
        storeParents(msg_id_to_msg_id, connection);

    } catch (Exception e) {
        Main.getLogger().error("Error storing messages for heuristic in-reply!", e);
    }
}

From source file:com.liferay.ide.maven.core.LiferayMavenProjectProvider.java

private String getNewDoctTypeSetting(String doctypeSetting, String newValue, Pattern p) {
    String newDoctTypeSetting = null;

    final Matcher m = p.matcher(doctypeSetting);

    if (m.find()) {
        String oldVersionString = m.group(m.groupCount());
        newDoctTypeSetting = doctypeSetting.replace(oldVersionString, newValue);
    }//from   w  w  w .  jav a  2s. c  om

    return newDoctTypeSetting;
}

From source file:org.apache.nifi.processors.standard.RouteText.java

private Group getGroup(final String line, final Pattern groupPattern) {
    if (groupPattern == null) {
        return EMPTY_GROUP;
    } else {//from  ww  w  . j  av a2  s.  c  o  m
        final Matcher matcher = groupPattern.matcher(line);
        if (matcher.matches()) {
            final List<String> capturingGroupValues = new ArrayList<>(matcher.groupCount());
            for (int i = 1; i <= matcher.groupCount(); i++) {
                capturingGroupValues.add(matcher.group(i));
            }
            return new Group(capturingGroupValues);
        } else {
            return EMPTY_GROUP;
        }
    }
}

From source file:net.pms.newgui.SelectRenderers.java

public void build() {
    JPanel checkPanel = new JPanel();
    checkPanel.applyComponentOrientation(ComponentOrientation.getOrientation(PMS.getLocale()));
    add(checkPanel, BorderLayout.LINE_START);
    allRenderers = new SearchableMutableTreeNode(Messages.getString("GeneralTab.13"));

    Pattern pattern = Pattern.compile("^\\s*([^\\s]*) ?([^\\s].*?)?\\s*$");
    for (String renderer : RendererConfiguration.getAllRenderersNames()) {
        Matcher match = pattern.matcher(renderer);
        if (match.find()) {
            // Find or create group or single name renderer
            SearchableMutableTreeNode node = null;
            try {
                node = allRenderers.findChild(match.group(1));
            } catch (IllegalChildException e) {
            }/*from w  w  w .java2 s .c o m*/
            if (node == null) {
                node = new SearchableMutableTreeNode(match.group(1));
                allRenderers.add(node);
            }
            // Find or create subgroup/name
            if (match.groupCount() > 1 && match.group(2) != null) {
                SearchableMutableTreeNode subNode = null;
                try {
                    subNode = node.findChild(match.group(2));
                } catch (IllegalChildException e) {
                }
                if (subNode != null) {
                    LOGGER.warn("Renderer {} found twice, ignoring repeated entry", renderer);
                } else {
                    subNode = new SearchableMutableTreeNode(match.group(2));
                    node.add(subNode);
                }
            }
        } else {
            LOGGER.warn("Can't parse renderer name \"{}\"", renderer);
        }
    }

    SrvTree = new JTree(new DefaultTreeModel(allRenderers));
    checkTreeManager = new CheckTreeManager(SrvTree);
    checkPanel.add(new JScrollPane(SrvTree));
    checkPanel.setSize(400, 500);
}

From source file:com.mercatis.lighthouse3.commons.commons.XmlMuncher.java

/**
 * This method takes a given document path and localizes - i.e. truncates -
 * it to the suffix left over when matching the given XPath expression
 * against the path./*from w ww.  j  a  v  a 2  s .  c om*/
 *
 * @param xpathExpression the XPath expression translated to a regular expression
 * @param path            the path to localize
 * @return <code>null</code>, if the XPath expression does not match the
 *         given path, the localized path suffix otherwise. Note that
 *         <code>""</code> is returned as a suffix when the XPath expression
 *         fully matches the path.
 */
private String localizePath(Pattern xpathExpression, String path) {
    String localizedPath = null;

    Matcher matcher = xpathExpression.matcher(path);
    if (matcher.find()) {
        String replacement = "/" + matcher.group(matcher.groupCount());
        localizedPath = matcher.replaceFirst(replacement);
    }

    return localizedPath;
}

From source file:com.novartis.opensource.yada.plugin.Gatekeeper.java

/**
 * Retrieves and processes the security query, and validates the results per
 * the security specification//from  w w w  . j av  a2s . c  om
 * 
 * @param spec
 *          the security specification for the requested query
 * @throws YADASecurityException
 *           when there is an issue retrieving or processing the security
 *           query           
 */
@Override
public void applyExecutionPolicy() throws YADASecurityException {

    //TODO the security query executes for every iteration of the qname 
    // in the current request. a flag needs to be set somewhere to indicate
    // clearance has already been granted.  This can't be in YADAQuery because of caching.

    //TODO needs to support app targets as well as qname targets

    //TODO tests for auth failure, i.e., unauthorized
    //TODO tests for ignoring attempted plugin overrides
    //TODO make it impossible to execute a protector query as a primary query without a server-side flag set, or 
    //  perhaps some authorization (i.e., for testing, maybe with a content policy)  
    //  This will close an attack vector.
    //TODO support dependency injection for other methods in addition to token for execution policy

    List<SecurityPolicyRecord> spec = getSecurityPolicyRecords(EXECUTION_POLICY_CODE);
    List<SecurityPolicyRecord> prunedSpec = new ArrayList<>();
    // process security spec

    // query can be standard or json
    //  if json, need name of column to map to token
    //  if standard, need list of relevant indices

    String policyColumns = getArgumentValue(EXECUTION_POLICY_COLUMNS);
    String policyIndices = getArgumentValue(EXECUTION_POLICY_INDICES);
    policyIndices = policyIndices == null ? getArgumentValue(EXECUTION_POLICY_INDEXES) : policyIndices;
    String polColParams_rx = "^((" + RX_IDX_INJECTION + "|[\\d]+)\\s?)+$";
    String polColJSONParams_rx = "^((" + RX_COL_INJECTION + "|[A-Za-z0-9_]+)\\s?)+$";
    String result = "";
    int index = -1;
    String injectedIndex = "";
    boolean policyHasParams = false;
    boolean policyHasJSONParams = false;
    boolean reqHasParams = getYADARequest().getParams() == null || getYADARequest().getParams().length == 0
            ? false
            : true;
    boolean reqHasJSONParams = YADAUtils.hasJSONParams(getYADARequest());

    for (SecurityPolicyRecord secRec : spec) {
        // Are params required for security query?
        if (policyIndices != null && policyIndices.matches(polColParams_rx)) {
            policyHasParams = true;
        }

        if (policyColumns != null && policyColumns.matches(polColJSONParams_rx)) {
            policyHasJSONParams = true;
        }

        // request and policy must have syntax compatibility, i.e., matching param syntax, or no params
        if ((policyHasParams && !reqHasJSONParams) || (policyHasJSONParams && !reqHasParams)
                || (!policyHasParams && reqHasJSONParams) || (!policyHasJSONParams && reqHasParams)
                || !(policyHasParams || reqHasParams || policyHasJSONParams || reqHasJSONParams)) {
            // confirm sec spec is config properly
            if (hasValidPolicy(secRec.getType())) // whitelist or blacklist
            {
                // confirm sec spec is mapped to requested query
                try {
                    new Finder().getQuery(secRec.getA11nQname());
                } catch (YADAFinderException e) {
                    String msg = "Unauthorized. Authorization qname not found.";
                    throw new YADASecurityException(msg);
                } catch (YADAConnectionException | YADAQueryConfigurationException e) {
                    String msg = "Unauthorized. Unable to check for security query. This could be a temporary issue.";
                    throw new YADASecurityException(msg, e);
                }
                // security query exists
            } else {
                String msg = "Unauthorized, due to policy misconfiguration. Must be \"blacklist\" or \"whitelist.\"";
                throw new YADASecurityException(msg);
            }
            prunedSpec.add(secRec);
        }
    }

    // kill the query if there aren't any compatible specs
    if (prunedSpec.size() == 0) {
        String msg = "Unauthorized. Request parameter syntax is incompatible with policy.";
        throw new YADASecurityException(msg);
    }

    // process the relevant specs
    for (SecurityPolicyRecord secRec : prunedSpec) // policy code (E,C), policy type (white,black), target (qname), A11nqname
    {
        String a11nQname = secRec.getA11nQname();
        String policyType = secRec.getType();

        // policy has params and req has compatible params 
        if (policyHasParams && !reqHasJSONParams) {
            @SuppressWarnings("null")
            String[] polCols = policyIndices.split("\\s");
            StringBuilder polVals = new StringBuilder();

            if (reqHasParams) {
                for (int i = 0; i < polCols.length; i++) {
                    // handle as params
                    // 1. get params from query
                    List<String> vals = getYADAQuery().getVals(0);
                    try {
                        index = Integer.parseInt(polCols[i]);
                    } catch (NumberFormatException e) {
                        injectedIndex = polCols[i];
                    }
                    // 2. pass user column
                    if (polVals.length() > 0)
                        polVals.append(",");

                    if (injectedIndex.equals("") && index > -1) {
                        if (index >= vals.size())
                            polVals.append((String) getToken());
                        else
                            polVals.append(vals.get(index));
                    } else {
                        Pattern rxInjection = Pattern.compile(RX_IDX_INJECTION);
                        Matcher m1 = rxInjection.matcher(injectedIndex);
                        if (m1.matches() && m1.groupCount() == 3) // injection
                        {
                            // parse regex: this is where the method value is injected
                            String colIdx = m1.group(2);
                            String colval = m1.group(3);

                            // find and execute injected method
                            String method = colval.substring(0, colval.indexOf('('));
                            String arg = colval.substring(colval.indexOf('(') + 1, colval.indexOf(')'));
                            Object val = null;
                            try {
                                if (arg.equals(""))
                                    val = getClass().getMethod(method).invoke(this, new Object[] {});
                                else
                                    val = getClass().getMethod(method, new Class[] { java.lang.String.class })
                                            .invoke(this, new Object[] { arg });
                            } catch (NoSuchMethodException | SecurityException | IllegalAccessException
                                    | IllegalArgumentException | InvocationTargetException e) {
                                String msg = "Unathorized. Injected method invocation failed.";
                                throw new YADASecurityException(msg, e);
                            }

                            // add/replace item in dataRow 
                            polVals.append(val);
                        }
                    }
                    index = -1;
                    injectedIndex = "";
                }
                // 3. execute the security query
                result = YADAUtils.executeYADAGet(new String[] { a11nQname },
                        new String[] { polVals.toString() });
            } else {
                for (int i = 0; i < polCols.length; i++) {
                    polVals.append((String) getToken());
                }
                result = YADAUtils.executeYADAGet(new String[] { a11nQname },
                        new String[] { polVals.toString() });
            }
        }
        // policy has JSONParams and req has compatible JSONParams
        else if (policyHasJSONParams && reqHasJSONParams) {
            LOG.warn("Could not parse column value into integer -- it's probably a String");
            // handle as JSONParams
            // 1. get JSONParams from query (params)
            LinkedHashMap<String, String[]> dataRow = getYADAQuery().getDataRow(0);
            // 2. add user column if necessary
            @SuppressWarnings("null")
            String[] polCols = policyColumns.split("\\s");
            for (String colspec : polCols) {
                // dataRow can look like, e.g.: {COL1:val1,COL2:val2}
                // polCols can look like, e.g.: COL2 APP:getValue(TARGET)

                Pattern rxInjection = Pattern.compile(RX_COL_INJECTION);
                Matcher m1 = rxInjection.matcher(colspec);
                if (m1.matches() && m1.groupCount() == 3) // injection
                {
                    // parse regex: this is where the method value is injected
                    String colname = m1.group(2);
                    String colval = m1.group(3);

                    // find and execute injected method
                    String method = colval.substring(0, colval.indexOf('('));
                    String arg = colval.substring(colval.indexOf('(') + 1, colval.indexOf(')'));
                    Object val = null;
                    try {
                        if (arg.equals(""))
                            val = getClass().getMethod(method).invoke(this, new Object[] {});
                        else
                            val = getClass().getMethod(method, new Class[] { java.lang.String.class })
                                    .invoke(this, new Object[] { arg });
                    } catch (NoSuchMethodException | SecurityException | IllegalAccessException
                            | IllegalArgumentException | InvocationTargetException e) {
                        String msg = "Unathorized. Injected method invocation failed.";
                        throw new YADASecurityException(msg, e);
                    }

                    // add/replace item in dataRow 
                    dataRow.put(colname, new String[] { (String) val });
                } else {
                    if (!dataRow.containsKey(colspec)) // no injection AND no parameter
                    {
                        String msg = "Unathorized. Injected method invocation failed.";
                        throw new YADASecurityException(msg);
                    }
                }
            }

            // 3. execute the security query
            JSONParamsEntry jpe = new JSONParamsEntry();
            // dataRow now contains injected values () or passed values
            // if values were injected, they've overwritten the passed in version
            jpe.addData(dataRow);
            JSONParams jp = new JSONParams(a11nQname, jpe);
            result = YADAUtils.executeYADAGetWithJSONParamsNoStats(jp);
        } else {
            // no parameters to pass to execution.policy query
            result = YADAUtils.executeYADAGet(new String[] { a11nQname }, new String[0]);
        }
        // parse result
        int count = new JSONObject(result).getJSONObject("RESULTSET").getInt("records");

        // Reject if necessary
        if ((isWhitelist(policyType) && count == 0) || (isBlacklist(policyType) && count > 0))
            throw new YADASecurityException("Unauthorized.");
    }

    this.clearSecurityPolicy();
}

From source file:com.gargoylesoftware.htmlunit.javascript.regexp.HtmlUnitRegExpProxy.java

private void setProperties(final Matcher matcher, final String thisString, final int startPos,
        final int endPos) {
    // lastMatch//from  w  w w  .j a  v a 2s  . co  m
    final String match = matcher.group();
    if (match == null) {
        lastMatch = new SubString();
    } else {
        lastMatch = new SubString(match, 0, match.length());
    }

    // parens
    final int groupCount = matcher.groupCount();
    if (groupCount == 0) {
        parens = null;
    } else {
        final int count = Math.min(9, groupCount);
        parens = new SubString[count];
        for (int i = 0; i < count; i++) {
            final String group = matcher.group(i + 1);
            if (group == null) {
                parens[i] = new SubString();
            } else {
                parens[i] = new SubString(group, 0, group.length());
            }
        }
    }

    // lastParen
    if (groupCount > 0) {
        if (groupCount > 9 && browserVersion_.hasFeature(JS_REGEXP_EMPTY_LASTPAREN_IF_TOO_MANY_GROUPS)) {
            lastParen = new SubString();
        } else {
            final String last = matcher.group(groupCount);
            if (last == null) {
                lastParen = new SubString();
            } else {
                lastParen = new SubString(last, 0, last.length());
            }
        }
    }

    // leftContext
    if (startPos > 0) {
        leftContext = new SubString(thisString, 0, startPos);
    } else {
        leftContext = new SubString();
    }

    // rightContext
    final int length = thisString.length();
    if (endPos < length) {
        rightContext = new SubString(thisString, endPos, length - endPos);
    } else {
        rightContext = new SubString();
    }
}

From source file:dk.dma.msinm.user.security.SecurityConf.java

/**
 * Parses a checkedResource configuration value.
 * @param value the value to parse//from w ww  .j ava 2  s.c  o m
 */
private void parseCheckedResource(String value) throws Exception {
    // Check the supported formats

    // Format 1: uri
    Matcher m = CHECKED_RESOURCE_PATTERN_1.matcher(value.trim());

    // Format 2: uri roles=r1,r2,r3
    if (!m.matches()) {
        m = CHECKED_RESOURCE_PATTERN_2.matcher(value.trim());
    }

    // Format 3: uri roles=r1,r2,r3 redirect=uri
    if (!m.matches()) {
        m = CHECKED_RESOURCE_PATTERN_3.matcher(value.trim());
    }

    if (!m.matches()) {
        throw new Exception("Invalid format at checkedResource: " + value);
    }

    String resource = m.group(1);
    String roles = m.groupCount() > 1 ? m.group(2) : null;
    String redirect = m.groupCount() > 2 ? m.group(3) : null;

    checkedResources.add(new CheckedResource(resource, roles, redirect));
}

From source file:io.kahu.hawaii.util.call.http.util.UriBuilder.java

private void substitutePathVariables(StringBuilder builder, String url) {
    Matcher matcher = pathVariablePattern.matcher(url);

    int currentPos = 0;
    int matchNumber = 0;
    while (matcher.find()) {
        int matchStart = matcher.start();
        if (matchStart > currentPos) {
            builder.append(url.substring(currentPos, matchStart));
        }/*from   w  ww.  jav  a 2  s. co m*/
        builder.append(pathVariables[matchNumber]);

        currentPos = matcher.end();
        matchNumber++;
    }
    if (currentPos < url.length()) {
        builder.append(url.substring(currentPos));
    }
    if (matchNumber != pathVariables.length) {
        System.err.println("Substitution for '" + url + "' got '" + pathVariables.length
                + "' variables and the number of groups is '" + matcher.groupCount() + "'.");
    }
}