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

io.jsync.http.impl.WebSocketMatcher Maven / Gradle / Ivy

There is a newer version: 1.10.13
Show newest version
/*
 * Copyright (c) 2011-2013 The original author or authors
 * ------------------------------------------------------
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * and Apache License v2.0 which accompanies this distribution.
 *
 *     The Eclipse Public License is available at
 *     http://www.eclipse.org/legal/epl-v10.html
 *
 *     The Apache License v2.0 is available at
 *     http://www.opensource.org/licenses/apache2.0.php
 *
 * You may elect to redistribute this code under either of these licenses.
 */

package io.jsync.http.impl;

import io.jsync.Handler;
import io.jsync.http.ServerWebSocket;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author Tim Fox
 */
public class WebSocketMatcher implements Handler {

  private final List bindings = new ArrayList<>();

  private Map params;
  private Handler handler;
  private Handler noMatchHandler;

  @Override
  public void handle(ServerWebSocket ws) {
    String path = ws.path();
    for (PatternBinding binding: bindings) {
      Matcher m = binding.pattern.matcher(path);
      if (m.matches()) {
        params = new HashMap<>(m.groupCount());
        if (binding.paramNames != null) {
          // Named params
          for (String param: binding.paramNames) {
            params.put(param, m.group(param));
          }
        } else {
          // Un-named params
          for (int i = 0; i < m.groupCount(); i++) {
            params.put("param" + i, m.group(i + 1));
          }
        }
        handler = binding.handler;
        handler.handle(new Match(params, ws));
        params = null;
        handler = null;
        return;
      }
    }
    if (noMatchHandler != null) {
      noMatchHandler.handle(new Match(null, ws));
    } else {
      ws.reject();
    }
  }

  public void addRegEx(String regex, Handler handler) {
    PatternBinding binding = new PatternBinding(Pattern.compile(regex), null, handler);
    bindings.add(binding);
  }

  public void addPattern(String pattern, Handler handler) {
    // We need to search for any : tokens in the String and replace them with named capture groups
    Matcher m =  Pattern.compile(":([A-Za-z][A-Za-z0-9]*)").matcher(pattern);
    StringBuffer sb = new StringBuffer();
    Set groups = new HashSet<>();
    while (m.find()) {
      String group = m.group().substring(1);
      if (groups.contains(group)) {
        throw new IllegalArgumentException("Cannot use identifier " + group + " more than once in pattern string");
      }
      m.appendReplacement(sb, "(?<$1>[^\\/]+)");
      groups.add(group);
    }
    m.appendTail(sb);
    String regex = sb.toString();
    PatternBinding binding = new PatternBinding(Pattern.compile(regex), groups, handler);
    bindings.add(binding);
  }

  /**
   * Specify a handler that will be called when no other handlers match.
   * If this handler is not specified default behaviour is to reject the websocket
   * (i.e. return 404 to the websocket client in the handshake)
   */
  public void noMatch(Handler handler) {
    noMatchHandler = handler;
  }

  private static class PatternBinding {
    final Pattern pattern;
    final Handler handler;
    final Set paramNames;

    private PatternBinding(Pattern pattern,  Set paramNames, Handler handler) {
      this.pattern = pattern;
      this.paramNames = paramNames;
      this.handler = handler;
    }
  }

  public static class Match {
    public final Map params;
    public final ServerWebSocket ws;

    public Match(Map params, ServerWebSocket ws) {
      this.params = params;
      this.ws = ws;
    }
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy