/* * Copyright 2013 ENERKO Informatik GmbH * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package de.enerko.reports2.engine; import static de.enerko.reports2.utils.Unchecker.uncheck; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.regex.Pattern; import oracle.jdbc.OracleConnection; import oracle.jdbc.OraclePreparedStatement; /** * This is a heloer class that retrives arguments vor PL/SQL procedures and functions * @author Michael J. Simons, 2013-06-17 */ public class ArgumentResolver { /** * Thrown if a procedure or function is not found in global or package scope */ public static class MethodNotFoundException extends RuntimeException { private static final long serialVersionUID = 1044851139822866147L; public final String methodName; public MethodNotFoundException(String methodName) { super(String.format("Method '%s' not found!", methodName)); this.methodName = methodName; } } private final OracleConnection connection; public ArgumentResolver(OracleConnection connection) { this.connection = connection; } /** * Determines the list of all arguments of a given Oracle PL/SQL procedure or function. * * @param fqn The fully qualified name of a procedure or function * @return a list of parameters (all real arguments, not the type of a function) */ public List<FormalArgument> getArguments(final String fqn) { final List<FormalArgument> rv = new ArrayList<FormalArgument>(); String packageName = null; String procedureName = null; if(fqn.indexOf('.') < 0) procedureName = fqn; else { final String[] tmp = fqn.split(Pattern.quote(".")); packageName = tmp[0]; procedureName = tmp[1]; } OraclePreparedStatement statement = null; ResultSet rs = null; try { // check if the procedure or function exists statement = (OraclePreparedStatement) this.connection.prepareStatement( "Select count(*) as cnt " + " from user_procedures p " + " where " + " (" + " lower(p.object_name) = lower(:package_name) and " + " lower(p.procedure_name) = lower(:procedure_name) " + " ) " + " or lower(p.object_name) = lower(:procedure_name)" ); statement.setStringAtName("package_name", packageName); statement.setStringAtName("procedure_name", procedureName); rs = statement.executeQuery(); rs.next(); if(rs.getInt("cnt") != 1) throw new MethodNotFoundException(fqn); rs.close(); statement.close(); // get arguments statement = (OraclePreparedStatement) this.connection.prepareStatement( "Select a.position as position, " + " lower(a.argument_name) as argument_name, " + " a.type_name, " + " a.data_type, " + " decode(DEFAULTED, 'Y', 'true', 'false') as defaulted " + " from user_arguments a " + " join user_procedures p on (p.object_name = a.package_name and p.procedure_name = a.object_name or a.package_name IS NULL and p.object_name = a.object_name) " + " where a.position > 0 " + // don't retrieve the type of a function " and a.sequence >= 1 " + // and not it's name " and a.argument_name is not null " + // don't retrive the type of a pipelined function " and lower(nvl(a.package_name, '-')) = lower(nvl(:package_name, '-')) and lower(a.object_name) = lower(:procedure_name) " + " order by a.position asc" ); statement.setStringAtName("package_name", packageName); statement.setStringAtName("procedure_name", procedureName); rs = statement.executeQuery(); while(rs.next()) rv.add(new FormalArgument(rs.getInt("position"), rs.getString("argument_name"), rs.getString("data_type"))); rs.close(); statement.close(); } catch(SQLException e) { throw uncheck(e); } finally { try { if(rs != null) rs.close(); } catch (SQLException e) { } try { if(statement != null) statement.close(); } catch (SQLException e) { } } Collections.sort(rv); return rv; } }