From 2ea69c37c69af28519a8bb0a26cd4f978a146a5f Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Sun, 15 Nov 2015 13:36:37 +0100 Subject: [PATCH] Avoid NPE for anonymous SqlParameter in CallMetaDataContext Issue: SPR-13628 (cherry picked from commit d1f5ee2) --- .../core/metadata/CallMetaDataContext.java | 116 +++++++++--------- 1 file changed, 61 insertions(+), 55 deletions(-) diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallMetaDataContext.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallMetaDataContext.java index 70daa10b55d..45b496aa771 100755 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallMetaDataContext.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallMetaDataContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -280,88 +280,94 @@ public class CallMetaDataContext { * Reconcile the provided parameters with available metadata and add new ones where appropriate. */ protected List reconcileParameters(List parameters) { - final List declaredReturnParameters = new ArrayList(); - final Map declaredParameters = new LinkedHashMap(); + final List declaredReturnParams = new ArrayList(); + final Map declaredParams = new LinkedHashMap(); boolean returnDeclared = false; - List outParameterNames = new ArrayList(); - List metaDataParameterNames = new ArrayList(); + List outParamNames = new ArrayList(); + List metaDataParamNames = new ArrayList(); // Get the names of the meta data parameters for (CallParameterMetaData meta : this.metaDataProvider.getCallParameterMetaData()) { if (meta.getParameterType() != DatabaseMetaData.procedureColumnReturn) { - metaDataParameterNames.add(meta.getParameterName().toLowerCase()); + metaDataParamNames.add(meta.getParameterName().toLowerCase()); } } // Separate implicit return parameters from explicit parameters... - for (SqlParameter parameter : parameters) { - if (parameter.isResultsParameter()) { - declaredReturnParameters.add(parameter); + for (SqlParameter param : parameters) { + if (param.isResultsParameter()) { + declaredReturnParams.add(param); } else { - String parameterNameToMatch = this.metaDataProvider.parameterNameToUse(parameter.getName()).toLowerCase(); - declaredParameters.put(parameterNameToMatch, parameter); - if (parameter instanceof SqlOutParameter) { - outParameterNames.add(parameter.getName()); - if (isFunction() && !metaDataParameterNames.contains(parameterNameToMatch)) { + String paramName = param.getName(); + if (paramName == null) { + throw new IllegalArgumentException("Anonymous parameters not supported for calls - " + + "please specify a name for the parameter of SQL type " + param.getSqlType()); + } + String paramNameToMatch = this.metaDataProvider.parameterNameToUse(paramName).toLowerCase(); + declaredParams.put(paramNameToMatch, param); + if (param instanceof SqlOutParameter) { + outParamNames.add(paramName); + if (isFunction() && !metaDataParamNames.contains(paramNameToMatch)) { if (!returnDeclared) { if (logger.isDebugEnabled()) { - logger.debug("Using declared out parameter '" + parameter.getName() + "' for function return value"); + logger.debug("Using declared out parameter '" + paramName + + "' for function return value"); } - setFunctionReturnName(parameter.getName()); + setFunctionReturnName(paramName); returnDeclared = true; } } } } } - setOutParameterNames(outParameterNames); + setOutParameterNames(outParamNames); - List workParameters = new ArrayList(); - workParameters.addAll(declaredReturnParameters); + List workParams = new ArrayList(); + workParams.addAll(declaredReturnParams); if (!this.metaDataProvider.isProcedureColumnMetaDataUsed()) { - workParameters.addAll(declaredParameters.values()); - return workParameters; + workParams.addAll(declaredParams.values()); + return workParams; } Map limitedInParamNamesMap = new HashMap(this.limitedInParameterNames.size()); - for (String limitedParameterName : this.limitedInParameterNames) { + for (String limitedParamName : this.limitedInParameterNames) { limitedInParamNamesMap.put( - this.metaDataProvider.parameterNameToUse(limitedParameterName).toLowerCase(), limitedParameterName); + this.metaDataProvider.parameterNameToUse(limitedParamName).toLowerCase(), limitedParamName); } for (CallParameterMetaData meta : this.metaDataProvider.getCallParameterMetaData()) { - String parNameToCheck = null; + String paramNameToCheck = null; if (meta.getParameterName() != null) { - parNameToCheck = this.metaDataProvider.parameterNameToUse(meta.getParameterName()).toLowerCase(); + paramNameToCheck = this.metaDataProvider.parameterNameToUse(meta.getParameterName()).toLowerCase(); } - String parNameToUse = this.metaDataProvider.parameterNameToUse(meta.getParameterName()); - if (declaredParameters.containsKey(parNameToCheck) || + String paramNameToUse = this.metaDataProvider.parameterNameToUse(meta.getParameterName()); + if (declaredParams.containsKey(paramNameToCheck) || (meta.getParameterType() == DatabaseMetaData.procedureColumnReturn && returnDeclared)) { - SqlParameter parameter; + SqlParameter param; if (meta.getParameterType() == DatabaseMetaData.procedureColumnReturn) { - parameter = declaredParameters.get(getFunctionReturnName()); - if (parameter == null && getOutParameterNames().size() > 0) { - parameter = declaredParameters.get(getOutParameterNames().get(0).toLowerCase()); + param = declaredParams.get(getFunctionReturnName()); + if (param == null && getOutParameterNames().size() > 0) { + param = declaredParams.get(getOutParameterNames().get(0).toLowerCase()); } - if (parameter == null) { + if (param == null) { throw new InvalidDataAccessApiUsageException( "Unable to locate declared parameter for function return value - " + - " add a SqlOutParameter with name \"" + getFunctionReturnName() +"\""); + " add a SqlOutParameter with name '" + getFunctionReturnName() + "'"); } else { - setFunctionReturnName(parameter.getName()); + setFunctionReturnName(param.getName()); } } else { - parameter = declaredParameters.get(parNameToCheck); + param = declaredParams.get(paramNameToCheck); } - if (parameter != null) { - workParameters.add(parameter); + if (param != null) { + workParams.add(param); if (logger.isDebugEnabled()) { - logger.debug("Using declared parameter for: " + - (parNameToUse == null ? getFunctionReturnName() : parNameToUse)); + logger.debug("Using declared parameter for '" + + (paramNameToUse != null ? paramNameToUse : getFunctionReturnName()) + "'"); } } } @@ -370,49 +376,49 @@ public class CallMetaDataContext { if (!isFunction() && !isReturnValueRequired() && this.metaDataProvider.byPassReturnParameter(meta.getParameterName())) { if (logger.isDebugEnabled()) { - logger.debug("Bypassing metadata return parameter for: " + meta.getParameterName()); + logger.debug("Bypassing metadata return parameter for '" + meta.getParameterName() + "'"); } } else { String returnNameToUse =(StringUtils.hasLength(meta.getParameterName()) ? - parNameToUse : getFunctionReturnName()); - workParameters.add(this.metaDataProvider.createDefaultOutParameter(returnNameToUse, meta)); + paramNameToUse : getFunctionReturnName()); + workParams.add(this.metaDataProvider.createDefaultOutParameter(returnNameToUse, meta)); if (isFunction()) { setFunctionReturnName(returnNameToUse); - outParameterNames.add(returnNameToUse); + outParamNames.add(returnNameToUse); } if (logger.isDebugEnabled()) { - logger.debug("Added metadata return parameter for: " + returnNameToUse); + logger.debug("Added metadata return parameter for '" + returnNameToUse + "'"); } } } else { if (meta.getParameterType() == DatabaseMetaData.procedureColumnOut) { - workParameters.add(this.metaDataProvider.createDefaultOutParameter(parNameToUse, meta)); - outParameterNames.add(parNameToUse); + workParams.add(this.metaDataProvider.createDefaultOutParameter(paramNameToUse, meta)); + outParamNames.add(paramNameToUse); if (logger.isDebugEnabled()) { - logger.debug("Added metadata out parameter for: " + parNameToUse); + logger.debug("Added metadata out parameter for '" + paramNameToUse + "'"); } } else if (meta.getParameterType() == DatabaseMetaData.procedureColumnInOut) { - workParameters.add(this.metaDataProvider.createDefaultInOutParameter(parNameToUse, meta)); - outParameterNames.add(parNameToUse); + workParams.add(this.metaDataProvider.createDefaultInOutParameter(paramNameToUse, meta)); + outParamNames.add(paramNameToUse); if (logger.isDebugEnabled()) { - logger.debug("Added metadata in out parameter for: " + parNameToUse); + logger.debug("Added metadata in out parameter for '" + paramNameToUse + "'"); } } else { if (this.limitedInParameterNames.isEmpty() || - limitedInParamNamesMap.containsKey(parNameToUse.toLowerCase())) { - workParameters.add(this.metaDataProvider.createDefaultInParameter(parNameToUse, meta)); + limitedInParamNamesMap.containsKey(paramNameToUse.toLowerCase())) { + workParams.add(this.metaDataProvider.createDefaultInParameter(paramNameToUse, meta)); if (logger.isDebugEnabled()) { - logger.debug("Added metadata in parameter for: " + parNameToUse); + logger.debug("Added metadata in parameter for '" + paramNameToUse + "'"); } } else { if (logger.isDebugEnabled()) { logger.debug("Limited set of parameters " + limitedInParamNamesMap.keySet() + - " skipped parameter for: " + parNameToUse); + " skipped parameter for '" + paramNameToUse + "'"); } } } @@ -420,7 +426,7 @@ public class CallMetaDataContext { } } - return workParameters; + return workParams; } /**