wildfire chat server source initial submit
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2017 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.moquette.spi.impl.subscriptions;
|
||||
|
||||
/**
|
||||
* Internal use only class.
|
||||
*/
|
||||
public class Token {
|
||||
|
||||
static final Token EMPTY = new Token("");
|
||||
static final Token MULTI = new Token("#");
|
||||
static final Token SINGLE = new Token("+");
|
||||
final String name;
|
||||
|
||||
protected Token(String s) {
|
||||
name = s;
|
||||
}
|
||||
|
||||
protected String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
protected boolean match(Token t) {
|
||||
if (t == MULTI || t == SINGLE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this == MULTI || this == SINGLE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return equals(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 7;
|
||||
hash = 29 * hash + (this.name != null ? this.name.hashCode() : 0);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final Token other = (Token) obj;
|
||||
if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2017 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.moquette.spi.impl.subscriptions;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class Topic implements Serializable {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(Topic.class);
|
||||
|
||||
private static final long serialVersionUID = 2438799283749822L;
|
||||
|
||||
private final String topic;
|
||||
|
||||
private transient List<Token> tokens;
|
||||
|
||||
private transient boolean valid;
|
||||
|
||||
public Topic(String topic) {
|
||||
this.topic = topic;
|
||||
}
|
||||
|
||||
|
||||
public String getTopic() {
|
||||
return topic;
|
||||
}
|
||||
|
||||
|
||||
public List<Token> getTokens() {
|
||||
if (tokens == null) {
|
||||
try {
|
||||
tokens = parseTopic(topic);
|
||||
valid = true;
|
||||
} catch (ParseException e) {
|
||||
valid = false;
|
||||
LOG.error("Error parsing the topic: {}, message: {}", topic, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
private List<Token> parseTopic(String topic) throws ParseException {
|
||||
List<Token> res = new ArrayList<>();
|
||||
String[] splitted = topic.split("/");
|
||||
|
||||
if (splitted.length == 0) {
|
||||
res.add(Token.EMPTY);
|
||||
}
|
||||
|
||||
if (topic.endsWith("/")) {
|
||||
// Add a fictious space
|
||||
String[] newSplitted = new String[splitted.length + 1];
|
||||
System.arraycopy(splitted, 0, newSplitted, 0, splitted.length);
|
||||
newSplitted[splitted.length] = "";
|
||||
splitted = newSplitted;
|
||||
}
|
||||
|
||||
for (int i = 0; i < splitted.length; i++) {
|
||||
String s = splitted[i];
|
||||
if (s.isEmpty()) {
|
||||
// if (i != 0) {
|
||||
// throw new ParseException("Bad format of topic, expetec topic name between
|
||||
// separators", i);
|
||||
// }
|
||||
res.add(Token.EMPTY);
|
||||
} else if (s.equals("#")) {
|
||||
// check that multi is the last symbol
|
||||
if (i != splitted.length - 1) {
|
||||
throw new ParseException(
|
||||
"Bad format of topic, the multi symbol (#) has to be the last one after a separator",
|
||||
i);
|
||||
}
|
||||
res.add(Token.MULTI);
|
||||
} else if (s.contains("#")) {
|
||||
throw new ParseException("Bad format of topic, invalid subtopic name: " + s, i);
|
||||
} else if (s.equals("+")) {
|
||||
res.add(Token.SINGLE);
|
||||
} else if (s.contains("+")) {
|
||||
throw new ParseException("Bad format of topic, invalid subtopic name: " + s, i);
|
||||
} else {
|
||||
res.add(new Token(s));
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
if (tokens == null)
|
||||
getTokens();
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify if the 2 topics matching respecting the rules of MQTT Appendix A
|
||||
*
|
||||
* @param subscriptionTopic
|
||||
* the topic filter of the subscription
|
||||
* @return true if the two topics match.
|
||||
*/
|
||||
// TODO reimplement with iterators or with queues
|
||||
public boolean match(Topic subscriptionTopic) {
|
||||
List<Token> msgTokens = getTokens();
|
||||
List<Token> subscriptionTokens = subscriptionTopic.getTokens();
|
||||
int i = 0;
|
||||
for (; i < subscriptionTokens.size(); i++) {
|
||||
Token subToken = subscriptionTokens.get(i);
|
||||
if (subToken != Token.MULTI && subToken != Token.SINGLE) {
|
||||
if (i >= msgTokens.size()) {
|
||||
return false;
|
||||
}
|
||||
Token msgToken = msgTokens.get(i);
|
||||
if (!msgToken.equals(subToken)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (subToken == Token.MULTI) {
|
||||
return true;
|
||||
}
|
||||
if (subToken == Token.SINGLE) {
|
||||
// skip a step forward
|
||||
}
|
||||
}
|
||||
}
|
||||
// if last token was a SINGLE then treat it as an empty
|
||||
// if (subToken == Token.SINGLE && (i - msgTokens.size() == 1)) {
|
||||
// i--;
|
||||
// }
|
||||
return i == msgTokens.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return topic;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
Topic other = (Topic) obj;
|
||||
|
||||
return Objects.equals(this.topic, other.topic);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return topic.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method
|
||||
* */
|
||||
public static Topic asTopic(String s) {
|
||||
return new Topic(s);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user