001/*
002MIT License
003
004Copyright (c) 2020 FBSQL Team
005
006Permission is hereby granted, free of charge, to any person obtaining a copy
007of this software and associated documentation files (the "Software"), to deal
008in the Software without restriction, including without limitation the rights
009to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
010copies of the Software, and to permit persons to whom the Software is
011furnished to do so, subject to the following conditions:
012
013The above copyright notice and this permission notice shall be included in all
014copies or substantial portions of the Software.
015
016THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
017IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
018FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
019AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
020LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
021OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
022SOFTWARE.
023
024Home:   https://fbsql.github.io
025E-Mail: fbsql.team@gmail.com
026*/
027
028package org.fbsql.antlr4.parser;
029
030import java.io.IOException;
031import java.io.InputStream;
032import java.net.URL;
033import java.util.Locale;
034
035import org.antlr.v4.runtime.CharStreams;
036import org.antlr.v4.runtime.CommonTokenStream;
037import org.antlr.v4.runtime.Lexer;
038import org.antlr.v4.runtime.tree.ParseTree;
039import org.antlr.v4.runtime.tree.ParseTreeWalker;
040import org.fbsql.antlr4.generated.FbsqlBaseListener;
041import org.fbsql.antlr4.generated.FbsqlLexer;
042import org.fbsql.antlr4.generated.FbsqlParser;
043import org.fbsql.antlr4.generated.FbsqlParser.Declare_procedure_stmtContext;
044import org.fbsql.antlr4.generated.FbsqlParser.JsonContext;
045import org.fbsql.antlr4.generated.FbsqlParser.Json_fileContext;
046import org.fbsql.servlet.DbServlet;
047import org.fbsql.servlet.NonNativeProcedure;
048import org.fbsql.servlet.ProcedureType;
049import org.fbsql.servlet.StringUtils;
050
051public class ParseStmtDeclareProcedure {
052        /**
053         * DECLARE PROCEDURE statement transfer object
054         * Declare stored procedure or function (can be used only in «init.sql» script)
055         */
056        public class StmtDeclareProcedure {
057                public String             procedure;
058                public NonNativeProcedure nonNativeProcedure;
059
060                @Override
061                public String toString() {
062                        return "StmtDeclareProcedure [procedure=" + procedure + ", nonNativeProcedure=" + nonNativeProcedure + "]";
063                }
064
065        }
066
067        private static final String USER_HOME_DIR = System.getProperty("user.home");
068
069        /**
070         * StmtDeclareProcedure transfer object
071         */
072        private StmtDeclareProcedure st;
073
074        public ParseStmtDeclareProcedure() {
075                st = new StmtDeclareProcedure();
076        }
077
078        /**
079         * DECLARE PROCEDURE Statement parser
080         *
081         * E.g.: DECLARE PROCEDURE GET_EMPLOYEES FOR "org.fbsql.examples.StoredProcedures::getEmployees";
082         *
083         * @param sql
084         * @return
085         */
086        public StmtDeclareProcedure parse(String sql) {
087                Lexer       lexer  = new FbsqlLexer(CharStreams.fromString(sql));
088                FbsqlParser parser = new FbsqlParser(new CommonTokenStream(lexer));
089                ParseTree   tree   = parser.declare_procedure_stmt();
090
091                ParseTreeWalker.DEFAULT.walk(new FbsqlBaseListener() {
092
093                        @Override
094                        public void enterDeclare_procedure_stmt(Declare_procedure_stmtContext ctx) {
095                                st.procedure = ctx.getChild(2).getText();
096                                String procedureTypeStr = ctx.getChild(4).getText().toUpperCase(Locale.ENGLISH);
097                                st.nonNativeProcedure               = new NonNativeProcedure();
098                                st.nonNativeProcedure.procedureType = ProcedureType.valueOf(procedureTypeStr);
099                                st.nonNativeProcedure.optionsJson = "{}"; // default OPTIONS clause
100                        }
101
102                        @Override
103                        public void enterJson(JsonContext ctx) {
104                                st.nonNativeProcedure.optionsJson = StringUtils.unquote(ctx.getText().trim());
105                        }
106
107                        @Override
108                        public void enterJson_file(Json_fileContext ctx) {
109                                String fileName = StringUtils.unquote(ctx.getText()).trim();
110                                String url;
111                                if (fileName.startsWith("http://") || fileName.startsWith("https://"))
112                                        url = fileName;
113                                else if (fileName.charAt(0) == '/')
114                                        url = "file://" + fileName;
115                                else
116                                        url = "file://" + USER_HOME_DIR + "/fbsql/config/init/" + fileName;
117
118                                try (InputStream is = new URL(url).openStream()) {
119                                        st.nonNativeProcedure.optionsJson = StringUtils.inputSreamToString(is);
120                                } catch (IOException e) {
121                                        e.printStackTrace();
122                                }
123                        }
124
125                }, tree);
126
127                if (DbServlet.DEBUG)
128                        System.out.println(st);
129
130                return st;
131        }
132}
133
134/*
135Please contact FBSQL Team by E-Mail fbsql.team@gmail.com
136or visit https://fbsql.github.io if you need additional
137information or have any questions.
138*/
139
140/* EOF */