com.espertech.esper.core.deploy.EPLModuleUtil Maven / Gradle / Ivy
/*
***************************************************************************************
* Copyright (C) 2006 EsperTech, Inc. All rights reserved. *
* http://www.espertech.com/esper *
* http://www.espertech.com *
* ---------------------------------------------------------------------------------- *
* The software in this package is published under the terms of the GPL license *
* a copy of which has been included with this distribution in the license.txt file. *
***************************************************************************************
*/
package com.espertech.esper.core.deploy;
import com.espertech.esper.client.EventType;
import com.espertech.esper.client.deploy.Module;
import com.espertech.esper.client.deploy.ModuleItem;
import com.espertech.esper.client.deploy.ParseException;
import com.espertech.esper.core.service.StatementEventTypeRef;
import com.espertech.esper.epl.core.EngineImportService;
import com.espertech.esper.epl.generated.EsperEPL2GrammarLexer;
import com.espertech.esper.epl.generated.EsperEPL2GrammarParser;
import com.espertech.esper.epl.parse.NoCaseSensitiveStream;
import com.espertech.esper.epl.parse.ParseHelper;
import com.espertech.esper.event.EventAdapterService;
import com.espertech.esper.event.EventTypeSPI;
import com.espertech.esper.filter.FilterService;
import org.antlr.v4.runtime.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.util.*;
public class EPLModuleUtil {
private static Logger log = LoggerFactory.getLogger(EPLModuleUtil.class);
/**
* Newline character.
*/
public static final String NEWLINE = System.getProperty("line.separator");
public static Module readInternal(InputStream stream, String resourceName) throws IOException, ParseException {
BufferedReader br = new BufferedReader(new InputStreamReader(stream));
StringWriter buffer = new StringWriter();
String strLine;
while ((strLine = br.readLine()) != null) {
buffer.append(strLine);
buffer.append(NEWLINE);
}
stream.close();
return parseInternal(buffer.toString(), resourceName);
}
public static Module parseInternal(String buffer, String resourceName) throws IOException, ParseException {
List semicolonSegments = EPLModuleUtil.parse(buffer.toString());
List nodes = new ArrayList();
for (EPLModuleParseItem segment : semicolonSegments) {
nodes.add(EPLModuleUtil.getModule(segment, resourceName));
}
String moduleName = null;
int count = 0;
for (ParseNode node : nodes) {
if (node instanceof ParseNodeComment) {
continue;
}
if (node instanceof ParseNodeModule) {
if (moduleName != null) {
throw new ParseException("Duplicate use of the 'module' keyword for resource '" + resourceName + "'");
}
if (count > 0) {
throw new ParseException("The 'module' keyword must be the first declaration in the module file for resource '" + resourceName + "'");
}
moduleName = ((ParseNodeModule) node).getModuleName();
}
count++;
}
Set uses = new LinkedHashSet();
Set imports = new LinkedHashSet();
count = 0;
for (ParseNode node : nodes) {
if ((node instanceof ParseNodeComment) || (node instanceof ParseNodeModule)) {
continue;
}
String message = "The 'uses' and 'import' keywords must be the first declaration in the module file or follow the 'module' declaration";
if (node instanceof ParseNodeUses) {
if (count > 0) {
throw new ParseException(message);
}
uses.add(((ParseNodeUses) node).getUses());
continue;
}
if (node instanceof ParseNodeImport) {
if (count > 0) {
throw new ParseException(message);
}
imports.add(((ParseNodeImport) node).getImported());
continue;
}
count++;
}
List items = new ArrayList();
for (ParseNode node : nodes) {
if ((node instanceof ParseNodeComment) || (node instanceof ParseNodeExpression)) {
boolean isComments = node instanceof ParseNodeComment;
items.add(new ModuleItem(node.getItem().getExpression(), isComments, node.getItem().getLineNum(), node.getItem().getStartChar(), node.getItem().getEndChar()));
}
}
return new Module(moduleName, resourceName, uses, imports, items, buffer);
}
public static List undeployTypes(Set referencedTypes, StatementEventTypeRef statementEventTypeRef, EventAdapterService eventAdapterService, FilterService filterService) {
List undeployedTypes = new ArrayList();
for (String typeName : referencedTypes) {
boolean typeInUse = statementEventTypeRef.isInUse(typeName);
if (typeInUse) {
if (log.isDebugEnabled()) {
log.debug("Event type '" + typeName + "' is in use, not removing type");
}
continue;
}
if (log.isDebugEnabled()) {
log.debug("Event type '" + typeName + "' is no longer in use, removing type");
}
EventType type = eventAdapterService.getExistsTypeByName(typeName);
if (type != null) {
EventTypeSPI spi = (EventTypeSPI) type;
if (!spi.getMetadata().isApplicationPreConfigured()) {
eventAdapterService.removeType(typeName);
undeployedTypes.add(spi);
filterService.removeType(spi);
}
}
}
return undeployedTypes;
}
public static ParseNode getModule(EPLModuleParseItem item, String resourceName) throws ParseException, IOException {
CharStream input = new NoCaseSensitiveStream(new StringReader(item.getExpression()));
EsperEPL2GrammarLexer lex = ParseHelper.newLexer(input);
CommonTokenStream tokenStream = new CommonTokenStream(lex);
tokenStream.fill();
List tokens = tokenStream.getTokens();
int beginIndex = 0;
boolean isMeta = false;
boolean isModule = false;
boolean isUses = false;
boolean isExpression = false;
while (beginIndex < tokens.size()) {
Token t = (Token) tokens.get(beginIndex);
if (t.getType() == EsperEPL2GrammarParser.EOF) {
break;
}
if ((t.getType() == EsperEPL2GrammarParser.WS) ||
(t.getType() == EsperEPL2GrammarParser.SL_COMMENT) ||
(t.getType() == EsperEPL2GrammarParser.ML_COMMENT)) {
beginIndex++;
continue;
}
String tokenText = t.getText().trim().toLowerCase(Locale.ENGLISH);
if (tokenText.equals("module")) {
isModule = true;
isMeta = true;
} else if (tokenText.equals("uses")) {
isUses = true;
isMeta = true;
} else if (tokenText.equals("import")) {
isMeta = true;
} else {
isExpression = true;
break;
}
beginIndex++;
beginIndex++; // skip space
break;
}
if (isExpression) {
return new ParseNodeExpression(item);
}
if (!isMeta) {
return new ParseNodeComment(item);
}
// check meta tag (module, uses, import)
StringWriter buffer = new StringWriter();
for (int i = beginIndex; i < tokens.size(); i++) {
Token t = (Token) tokens.get(i);
if (t.getType() == EsperEPL2GrammarParser.EOF) {
break;
}
if ((t.getType() != EsperEPL2GrammarParser.IDENT) &&
(t.getType() != EsperEPL2GrammarParser.DOT) &&
(t.getType() != EsperEPL2GrammarParser.STAR) &&
(!t.getText().matches("[a-zA-Z]*"))) {
throw getMessage(isModule, isUses, resourceName, t.getType());
}
buffer.append(t.getText().trim());
}
String result = buffer.toString().trim();
if (result.length() == 0) {
throw getMessage(isModule, isUses, resourceName, -1);
}
if (isModule) {
return new ParseNodeModule(item, result);
} else if (isUses) {
return new ParseNodeUses(item, result);
}
return new ParseNodeImport(item, result);
}
private static ParseException getMessage(boolean module, boolean uses, String resourceName, int type) {
String message = "Keyword '";
if (module) {
message += "module";
} else if (uses) {
message += "uses";
} else {
message += "import";
}
message += "' must be followed by a name or package name (set of names separated by dots) for resource '" + resourceName + "'";
if (type != -1) {
String tokenName = EsperEPL2GrammarParser.getLexerTokenParaphrases().get(type);
if (tokenName == null) {
tokenName = EsperEPL2GrammarParser.getParserTokenParaphrases().get(type);
}
if (tokenName != null) {
message += ", unexpected reserved keyword " + tokenName + " was encountered as part of the name";
}
}
return new ParseException(message);
}
public static List parse(String module) throws ParseException {
CharStream input;
try {
input = new NoCaseSensitiveStream(new StringReader(module));
} catch (IOException ex) {
log.error("Exception reading module expression: " + ex.getMessage(), ex);
return null;
}
EsperEPL2GrammarLexer lex = ParseHelper.newLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lex);
try {
tokens.fill();
} catch (RuntimeException ex) {
String message = "Unexpected exception recognizing module text";
if (ex instanceof LexerNoViableAltException) {
if (ParseHelper.hasControlCharacters(module)) {
message = "Unrecognized control characters found in text, failed to parse text";
} else {
message += ", recognition failed for " + ex.toString();
}
} else if (ex instanceof RecognitionException) {
RecognitionException recog = (RecognitionException) ex;
message += ", recognition failed for " + recog.toString();
} else if (ex.getMessage() != null) {
message += ": " + ex.getMessage();
}
message += " [" + module + "]";
log.error(message, ex);
throw new ParseException(message);
}
List statements = new ArrayList();
StringWriter current = new StringWriter();
Integer lineNum = null;
int charPosStart = 0;
int charPos = 0;
List tokenList = tokens.getTokens();
Set skippedSemicolonIndexes = getSkippedSemicolons(tokenList);
int index = -1;
// Call getTokens first before invoking tokens.size! ANTLR problem
for (Object token : tokenList) {
index++;
Token t = (Token) token;
boolean semi = t.getType() == EsperEPL2GrammarLexer.SEMI && !skippedSemicolonIndexes.contains(index);
if (semi) {
if (current.toString().trim().length() > 0) {
statements.add(new EPLModuleParseItem(current.toString().trim(), lineNum == null ? 0 : lineNum, charPosStart, charPos));
lineNum = null;
}
current = new StringWriter();
} else {
if ((lineNum == null) && (t.getType() != EsperEPL2GrammarParser.WS)) {
lineNum = t.getLine();
charPosStart = charPos;
}
if (t.getType() != EsperEPL2GrammarLexer.EOF) {
current.append(t.getText());
charPos += t.getText().length();
}
}
}
if (current.toString().trim().length() > 0) {
statements.add(new EPLModuleParseItem(current.toString().trim(), lineNum == null ? 0 : lineNum, 0, 0));
}
return statements;
}
public static Module readFile(File file) throws IOException, ParseException {
FileInputStream inputStream = null;
try {
inputStream = new FileInputStream(file);
return EPLModuleUtil.readInternal(inputStream, file.getAbsolutePath());
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
log.debug("Error closing input stream", e);
}
}
}
}
public static Module readResource(String resource, EngineImportService engineImportService) throws IOException, ParseException {
String stripped = resource.startsWith("/") ? resource.substring(1) : resource;
InputStream stream = null;
ClassLoader classLoader = engineImportService.getClassLoader();
if (classLoader != null) {
stream = classLoader.getResourceAsStream(stripped);
}
if (stream == null) {
stream = EPDeploymentAdminImpl.class.getResourceAsStream(resource);
}
if (stream == null) {
stream = EPDeploymentAdminImpl.class.getClassLoader().getResourceAsStream(stripped);
}
if (stream == null) {
throw new IOException("Failed to find resource '" + resource + "' in classpath");
}
try {
return EPLModuleUtil.readInternal(stream, resource);
} finally {
try {
stream.close();
} catch (IOException e) {
log.debug("Error closing input stream", e);
}
}
}
/**
* Find expression declarations and skip semicolon content between square brackets for scripts
*/
private static Set getSkippedSemicolons(List tokens) {
Set result = null;
int index = -1;
for (Object token : tokens) {
index++;
Token t = (Token) token;
if (t.getType() == EsperEPL2GrammarParser.EXPRESSIONDECL) {
if (result == null) {
result = new HashSet();
}
getSkippedSemicolonsBetweenSquareBrackets(index, tokens, result);
}
}
return result == null ? Collections.emptySet() : result;
}
/**
* Find content between square brackets
*/
private static void getSkippedSemicolonsBetweenSquareBrackets(int index, List tokens, Set result) {
// Handle EPL expression "{text}" and script expression "[text]"
int indexFirstCurly = indexFirstToken(index, tokens, EsperEPL2GrammarParser.LCURLY);
int indexFirstSquare = indexFirstToken(index, tokens, EsperEPL2GrammarParser.LBRACK);
if (indexFirstSquare == -1) {
return;
}
if (indexFirstCurly != -1 && indexFirstCurly < indexFirstSquare) {
return;
}
int indexCloseSquare = findEndSquareBrackets(indexFirstSquare, tokens);
if (indexCloseSquare == -1) {
return;
}
int current = indexFirstSquare;
while (current < indexCloseSquare) {
Token t = tokens.get(current);
if (t.getType() == EsperEPL2GrammarParser.SEMI) {
result.add(current);
}
current++;
}
}
private static int findEndSquareBrackets(int startIndex, List tokens) {
int index = startIndex + 1;
int squareBracketDepth = 0;
while (index < tokens.size()) {
Token t = tokens.get(index);
if (t.getType() == EsperEPL2GrammarParser.RBRACK) {
if (squareBracketDepth == 0) {
return index;
}
squareBracketDepth--;
}
if (t.getType() == EsperEPL2GrammarParser.LBRACK) {
squareBracketDepth++;
}
index++;
}
return -1;
}
private static int indexFirstToken(int startIndex, List tokens, int tokenType) {
int index = startIndex;
while (index < tokens.size()) {
Token t = tokens.get(index);
if (t.getType() == tokenType) {
return index;
}
index++;
}
return -1;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy