/* This file is part of VoltDB. * Copyright (C) 2008-2017 VoltDB Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with VoltDB. If not, see <http://www.gnu.org/licenses/>. */ package org.voltdb.compiler.statements; import java.util.regex.Matcher; import org.voltdb.catalog.Database; import org.voltdb.compiler.ClassMatcher.ClassNameMatchStatus; import org.voltdb.compiler.DDLCompiler; import org.voltdb.compiler.DDLCompiler.DDLStatement; import org.voltdb.compiler.DDLCompiler.StatementProcessor; import org.voltdb.compiler.VoltCompiler.DdlProceduresToLoad; import org.voltdb.compiler.VoltCompiler.VoltCompilerException; import org.voltdb.parser.SQLParser; import org.voltdb.utils.InMemoryJarfile; /** * Process IMPORT CLASS <class-name>, notice that this is deprecated. */ public class ImportClass extends StatementProcessor { public ImportClass(DDLCompiler ddlCompiler) { super(ddlCompiler); } @Override protected boolean processStatement(DDLStatement ddlStatement, Database db, DdlProceduresToLoad whichProcs) throws VoltCompilerException { // match IMPORT CLASS statements Matcher statementMatcher = SQLParser.matchImportClass(ddlStatement.statement); if (! statementMatcher.matches()) { return false; } if (whichProcs == DdlProceduresToLoad.ALL_DDL_PROCEDURES) { // Semi-hacky way of determining if we're doing a cluster-internal compilation. // Command-line compilation will never have an InMemoryJarfile. if (!(m_classLoader instanceof InMemoryJarfile.JarLoader)) { // Only process the statement if this is not for the StatementPlanner String classNameStr = statementMatcher.group(1); // check that the match pattern is a valid match pattern checkIdentifierWithWildcard(classNameStr, ddlStatement.statement); ClassNameMatchStatus matchStatus = m_classMatcher.addPattern(classNameStr); if (matchStatus == ClassNameMatchStatus.NO_EXACT_MATCH) { throw m_compiler.new VoltCompilerException(String.format( "IMPORT CLASS not found: '%s'", classNameStr)); // remove trailing semicolon } else if (matchStatus == ClassNameMatchStatus.NO_WILDCARD_MATCH) { m_compiler.addWarn(String.format( "IMPORT CLASS no match for wildcarded class: '%s'", classNameStr), ddlStatement.lineNo); } } else { m_compiler.addInfo("Internal cluster recompilation ignoring IMPORT CLASS line: " + ddlStatement.statement); } // Need to track the IMPORT CLASS lines even on internal compiles so that // we don't lose them from the DDL source. When the @UAC path goes away, // we could change this. m_tracker.addImportLine(ddlStatement.statement); } return true; } /** * Checks whether or not the start of the given identifier is java (and * thus DDL) compliant. An identifier may start with: _ [a-zA-Z] $ * * and contain subsequent characters including: _ [0-9a-zA-Z] $ * * @param identifier the identifier to check * @param statement the statement where the identifier is * @return the given identifier unmodified * @throws VoltCompilerException when it is not compliant */ private String checkIdentifierWithWildcard( final String identifier, final String statement ) throws VoltCompilerException { assert identifier != null && ! identifier.trim().isEmpty(); assert statement != null && ! statement.trim().isEmpty(); int loc = 0; do { if ( ! Character.isJavaIdentifierStart(identifier.charAt(loc)) && identifier.charAt(loc)!= '*') { String msg = "Unknown indentifier in DDL: \"" + statement.substring(0,statement.length()-1) + "\" contains invalid identifier \"" + identifier + "\""; throw m_compiler.new VoltCompilerException(msg); } loc++; while (loc < identifier.length() && identifier.charAt(loc) != '.') { if (! Character.isJavaIdentifierPart(identifier.charAt(loc)) && identifier.charAt(loc)!= '*') { String msg = "Unknown indentifier in DDL: \"" + statement.substring(0,statement.length()-1) + "\" contains invalid identifier \"" + identifier + "\""; throw m_compiler.new VoltCompilerException(msg); } loc++; } if (loc < identifier.length() && identifier.charAt(loc) == '.') { loc++; if (loc >= identifier.length()) { String msg = "Unknown indentifier in DDL: \"" + statement.substring(0,statement.length()-1) + "\" contains invalid identifier \"" + identifier + "\""; throw m_compiler.new VoltCompilerException(msg); } } } while( loc > 0 && loc < identifier.length()); return identifier; } }