Merge pull request #18288 from jcogs33/jcogs33/csrf-unprotected-request-type

Java: add CSRF query
This commit is contained in:
Jami
2025-02-11 15:32:56 -05:00
committed by GitHub
38 changed files with 1654 additions and 4 deletions

View File

@@ -0,0 +1,471 @@
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import static org.springframework.web.bind.annotation.RequestMethod.*;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.beans.factory.annotation.Autowired;
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import org.kohsuke.stapler.WebMethod;
import org.kohsuke.stapler.interceptor.RequirePOST;
import org.kohsuke.stapler.verb.POST;
import org.kohsuke.stapler.verb.GET;
import org.kohsuke.stapler.verb.PUT;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.HttpRedirect;
import org.kohsuke.stapler.HttpResponses;
import org.apache.ibatis.jdbc.SqlRunner;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import java.util.Map;
@Controller
public class CsrfUnprotectedRequestTypeTest {
public static Connection connection;
// Test Spring sources with `PreparedStatement.executeUpdate()` as a default database update method call
// BAD: allows request type not default-protected from CSRF when updating a database
@RequestMapping("/")
public void bad1() { // $ hasCsrfUnprotectedRequestType
try {
String sql = "DELETE";
Connection conn = DriverManager.getConnection("url");
PreparedStatement ps = conn.prepareStatement(sql);
ps.executeUpdate(); // database update method call
} catch (SQLException e) { }
}
// BAD: uses GET request when updating a database
@RequestMapping(value = "", method = RequestMethod.GET)
public void bad2() { // $ hasCsrfUnprotectedRequestType
try {
String sql = "DELETE";
Connection conn = DriverManager.getConnection("url");
PreparedStatement ps = conn.prepareStatement(sql);
ps.executeUpdate(); // database update method call
} catch (SQLException e) { }
}
// BAD: uses GET request when updating a database
@GetMapping(value = "")
public void bad3() { // $ hasCsrfUnprotectedRequestType
try {
String sql = "DELETE";
Connection conn = DriverManager.getConnection("url");
PreparedStatement ps = conn.prepareStatement(sql);
ps.executeUpdate(); // database update method call
} catch (SQLException e) { }
}
// BAD: allows GET request when updating a database
@RequestMapping(value = "", method = { RequestMethod.GET, RequestMethod.POST })
public void bad4() { // $ hasCsrfUnprotectedRequestType
try {
String sql = "DELETE";
Connection conn = DriverManager.getConnection("url");
PreparedStatement ps = conn.prepareStatement(sql);
ps.executeUpdate(); // database update method call
} catch (SQLException e) { }
}
// BAD: uses request type not default-protected from CSRF when updating a database
@RequestMapping(value = "", method = { GET, HEAD, OPTIONS, TRACE })
public void bad5() { // $ hasCsrfUnprotectedRequestType
try {
String sql = "DELETE";
Connection conn = DriverManager.getConnection("url");
PreparedStatement ps = conn.prepareStatement(sql);
ps.executeUpdate(); // database update method call
} catch (SQLException e) { }
}
// GOOD: uses OPTIONS or TRACE, which are unlikely to be exploitable via CSRF
@RequestMapping(value = "", method = { OPTIONS, TRACE })
public void good0() {
try {
String sql = "DELETE";
Connection conn = DriverManager.getConnection("url");
PreparedStatement ps = conn.prepareStatement(sql);
ps.executeUpdate(); // database update method call
} catch (SQLException e) { }
}
// GOOD: uses POST request when updating a database
@RequestMapping(value = "", method = RequestMethod.POST)
public void good1() {
try {
String sql = "DELETE";
Connection conn = DriverManager.getConnection("url");
PreparedStatement ps = conn.prepareStatement(sql);
ps.executeUpdate(); // database update method call
} catch (SQLException e) { }
}
// GOOD: uses POST request when updating a database
@RequestMapping(value = "", method = POST)
public void good2() {
try {
String sql = "DELETE";
Connection conn = DriverManager.getConnection("url");
PreparedStatement ps = conn.prepareStatement(sql);
ps.executeUpdate(); // database update method call
} catch (SQLException e) { }
}
// GOOD: uses POST request when updating a database
@PostMapping(value = "")
public void good3() {
try {
String sql = "DELETE";
Connection conn = DriverManager.getConnection("url");
PreparedStatement ps = conn.prepareStatement(sql);
ps.executeUpdate(); // database update method call
} catch (SQLException e) { }
}
// GOOD: uses a request type that is default-protected from CSRF when updating a database
@RequestMapping(value = "", method = { POST, PUT, PATCH, DELETE })
public void good4() {
try {
String sql = "DELETE";
Connection conn = DriverManager.getConnection("url");
PreparedStatement ps = conn.prepareStatement(sql);
ps.executeUpdate(); // database update method call
} catch (SQLException e) { }
}
// Test database update method calls other than `PreparedStatement.executeUpdate()`
// BAD: allows request type not default-protected from CSRF when
// updating a database using `PreparedStatement.executeLargeUpdate()`
@RequestMapping("/")
public void bad6() { // $ hasCsrfUnprotectedRequestType
try {
String sql = "DELETE";
Connection conn = DriverManager.getConnection("url");
PreparedStatement ps = conn.prepareStatement(sql);
ps.executeLargeUpdate(); // database update method call
} catch (SQLException e) { }
}
// BAD: allows request type not default-protected from CSRF when
// updating a database using `Statement.executeUpdate`
@RequestMapping("/")
public void badStatementExecuteUpdate() { // $ hasCsrfUnprotectedRequestType
try {
String item = "item";
String price = "price";
Statement statement = connection.createStatement();
String sql = "UPDATE PRODUCT SET PRICE='" + price + "' WHERE ITEM='" + item + "'";
int count = statement.executeUpdate(sql);
} catch (SQLException e) { }
}
// BAD: allows request type not default-protected from CSRF when
// updating a database using `Statement.executeLargeUpdate`
@RequestMapping("/")
public void badStatementExecuteLargeUpdate() { // $ hasCsrfUnprotectedRequestType
try {
String item = "item";
String price = "price";
Statement statement = connection.createStatement();
String sql = "UPDATE PRODUCT SET PRICE='" + price + "' WHERE ITEM='" + item + "'";
long count = statement.executeLargeUpdate(sql);
} catch (SQLException e) { }
}
// BAD: allows request type not default-protected from CSRF when
// updating a database using `Statement.execute` with SQL UPDATE
@RequestMapping("/")
public void badStatementExecute() { // $ hasCsrfUnprotectedRequestType
try {
String item = "item";
String price = "price";
Statement statement = connection.createStatement();
String sql = "UPDATE PRODUCT SET PRICE='" + price + "' WHERE ITEM='" + item + "'";
boolean bool = statement.execute(sql);
} catch (SQLException e) { }
}
// GOOD: does not update a database, queries with SELECT
@RequestMapping("/")
public void goodStatementExecute() {
try {
String category = "category";
Statement statement = connection.createStatement();
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ category + "' ORDER BY PRICE";
boolean bool = statement.execute(query);
} catch (SQLException e) { }
}
// BAD: allows request type not default-protected from CSRF when
// updating a database using `SqlRunner.insert`
@RequestMapping("/")
public void badSqlRunnerInsert() { // $ hasCsrfUnprotectedRequestType
try {
String item = "item";
String price = "price";
String sql = "INSERT PRODUCT SET PRICE='" + price + "' WHERE ITEM='" + item + "'";
SqlRunner sqlRunner = new SqlRunner(connection);
sqlRunner.insert(sql);
} catch (SQLException e) { }
}
// BAD: allows request type not default-protected from CSRF when
// updating a database using `SqlRunner.update`
@RequestMapping("/")
public void badSqlRunnerUpdate() { // $ hasCsrfUnprotectedRequestType
try {
String item = "item";
String price = "price";
String sql = "UPDATE PRODUCT SET PRICE='" + price + "' WHERE ITEM='" + item + "'";
SqlRunner sqlRunner = new SqlRunner(connection);
sqlRunner.update(sql);
} catch (SQLException e) { }
}
// BAD: allows request type not default-protected from CSRF when
// updating a database using `SqlRunner.delete`
@RequestMapping("/")
public void badSqlRunnerDelete() { // $ hasCsrfUnprotectedRequestType
try {
String item = "item";
String price = "price";
String sql = "DELETE PRODUCT SET PRICE='" + price + "' WHERE ITEM='" + item + "'";
SqlRunner sqlRunner = new SqlRunner(connection);
sqlRunner.delete(sql);
} catch (SQLException e) { }
}
// BAD: allows request type not default-protected from CSRF when
// updating a database using `JdbcTemplate.update`
@RequestMapping("/")
public void badJdbcTemplateUpdate() { // $ hasCsrfUnprotectedRequestType
String item = "item";
String price = "price";
String sql = "UPDATE PRODUCT SET PRICE='" + price + "' WHERE ITEM='" + item + "'";
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.update(sql);
}
// BAD: allows request type not default-protected from CSRF when
// updating a database using `JdbcTemplate.batchUpdate`
@RequestMapping("/")
public void badJdbcTemplateBatchUpdate() { // $ hasCsrfUnprotectedRequestType
String item = "item";
String price = "price";
String sql = "UPDATE PRODUCT SET PRICE='" + price + "' WHERE ITEM='" + item + "'";
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.batchUpdate(sql, null, null);
}
// BAD: allows request type not default-protected from CSRF when
// updating a database using `JdbcTemplate.execute`
@RequestMapping("/")
public void badJdbcTemplateExecute() { // $ hasCsrfUnprotectedRequestType
String item = "item";
String price = "price";
String sql = "UPDATE PRODUCT SET PRICE='" + price + "' WHERE ITEM='" + item + "'";
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.execute(sql);
}
// GOOD: does not update a database, queries with SELECT
@RequestMapping("/")
public void goodJdbcTemplateExecute() {
String category = "category";
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ category + "' ORDER BY PRICE";
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.execute(query);
}
// BAD: allows request type not default-protected from CSRF when
// updating a database using `NamedParameterJdbcTemplate.update`
@RequestMapping("/")
public void badNamedParameterJdbcTemplateUpdate() { // $ hasCsrfUnprotectedRequestType
String item = "item";
String price = "price";
String sql = "UPDATE PRODUCT SET PRICE='" + price + "' WHERE ITEM='" + item + "'";
JdbcTemplate jdbcTemplate = new JdbcTemplate();
NamedParameterJdbcTemplate namedParamJdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate);
namedParamJdbcTemplate.update(sql, null, null);
}
// BAD: allows request type not default-protected from CSRF when
// updating a database using `NamedParameterJdbcTemplate.batchUpdate`
@RequestMapping("/")
public void badNamedParameterJdbcTemplateBatchUpdate() { // $ hasCsrfUnprotectedRequestType
String item = "item";
String price = "price";
String sql = "UPDATE PRODUCT SET PRICE='" + price + "' WHERE ITEM='" + item + "'";
JdbcTemplate jdbcTemplate = new JdbcTemplate();
NamedParameterJdbcTemplate namedParamJdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate);
namedParamJdbcTemplate.batchUpdate(sql, (Map<String,?>[]) null);
}
// BAD: allows request type not default-protected from CSRF when
// updating a database using `NamedParameterJdbcTemplate.execute`
@RequestMapping("/")
public void badNamedParameterJdbcTemplateExecute() { // $ hasCsrfUnprotectedRequestType
String item = "item";
String price = "price";
String sql = "UPDATE PRODUCT SET PRICE='" + price + "' WHERE ITEM='" + item + "'";
JdbcTemplate jdbcTemplate = new JdbcTemplate();
NamedParameterJdbcTemplate namedParamJdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate);
namedParamJdbcTemplate.execute(sql, null);
}
// GOOD: does not update a database, queries with SELECT
@RequestMapping("/")
public void goodNamedParameterJdbcTemplateExecute() {
String category = "category";
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ category + "' ORDER BY PRICE";
JdbcTemplate jdbcTemplate = new JdbcTemplate();
NamedParameterJdbcTemplate namedParamJdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate);
namedParamJdbcTemplate.execute(query, null);
}
@Autowired
private MyBatisService myBatisService;
// BAD: uses GET request when updating a database with MyBatis XML mapper method
@GetMapping(value = "")
public void bad7(@RequestParam String name) { // $ hasCsrfUnprotectedRequestType
myBatisService.bad7(name);
}
// BAD: uses GET request when updating a database with MyBatis `@DeleteProvider`
@GetMapping(value = "badDelete")
public void badDelete(@RequestParam String name) { // $ hasCsrfUnprotectedRequestType
myBatisService.badDelete(name);
}
// BAD: uses GET request when updating a database with MyBatis `@UpdateProvider`
@GetMapping(value = "badUpdate")
public void badUpdate(@RequestParam String name) { // $ hasCsrfUnprotectedRequestType
myBatisService.badUpdate(name);
}
// BAD: uses GET request when updating a database with MyBatis `@InsertProvider`
@GetMapping(value = "badInsert")
public void badInsert(@RequestParam String name) { // $ hasCsrfUnprotectedRequestType
myBatisService.badInsert(name);
}
// BAD: uses GET request when updating a database with MyBatis `@Delete`
@GetMapping(value = "bad8")
public void bad8(@RequestParam int id) { // $ hasCsrfUnprotectedRequestType
myBatisService.bad8(id);
}
// BAD: uses GET request when updating a database with MyBatis `@Insert`
@GetMapping(value = "bad9")
public void bad9(@RequestParam String user) { // $ hasCsrfUnprotectedRequestType
myBatisService.bad9(user);
}
// BAD: uses GET request when updating a database with MyBatis `@Update`
@GetMapping(value = "bad10")
public void bad10(@RequestParam String user) { // $ hasCsrfUnprotectedRequestType
myBatisService.bad10(user);
}
// Test name-based heuristic for method names that imply a state-change
@GetMapping(value = "transfer")
public String transfer(@RequestParam String user) { return "transfer"; } // $ hasCsrfUnprotectedRequestType
@GetMapping(value = "transfer")
public String transferData(@RequestParam String user) { return "transfer"; } // $ hasCsrfUnprotectedRequestType
@GetMapping(value = "transfer")
public String doTransfer(@RequestParam String user) { return "transfer"; } // $ hasCsrfUnprotectedRequestType
@GetMapping(value = "transfer")
public String doTransferAllData(@RequestParam String user) { return "transfer"; } // $ hasCsrfUnprotectedRequestType
@GetMapping(value = "transfer")
public String doDataTransfer(@RequestParam String user) { return "transfer"; } // $ hasCsrfUnprotectedRequestType
@GetMapping(value = "transfer")
public String transfered(@RequestParam String user) { return "transfer"; } // OK: we look for 'transfer' only
@GetMapping(value = "transfer")
public String dotransfer(@RequestParam String user) { return "transfer"; } // OK: we look for 'transfer' within camelCase only
@GetMapping(value = "transfer")
public String doTransferdata(@RequestParam String user) { return "transfer"; } // OK: we look for 'transfer' within camelCase only
@GetMapping(value = "transfer")
public String getTransfer(@RequestParam String user) { return "transfer"; } // OK: starts with 'get'
// Test Stapler web methods with name-based heuristic
// BAD: Stapler web method annotated with `@WebMethod` and method name that implies a state-change
@WebMethod(name = "post")
public String doPost(String user) { // $ hasCsrfUnprotectedRequestType
return "post";
}
// GOOD: nothing to indicate that this is a Stapler web method
public String postNotAWebMethod(String user) {
return "post";
}
// GOOD: Stapler web method annotated with `@RequirePOST` and method name that implies a state-change
@RequirePOST
public String doPost1(String user) {
return "post";
}
// GOOD: Stapler web method annotated with `@POST` and method name that implies a state-change
@POST
public String doPost2(String user) {
return "post";
}
// BAD: Stapler web method annotated with `@GET` and method name that implies a state-change
@GET
public String doPost3(String user) { // $ hasCsrfUnprotectedRequestType
return "post";
}
// GOOD: Stapler web method annotated with `@PUT` and method name that implies a state-change
// We treat this case as good since PUT is only exploitable if there is a CORS issue.
@PUT
public String doPut(String user) {
return "put";
}
// BAD: Stapler web method parameter of type `StaplerRequest` and method name that implies a state-change
public String doPost4(StaplerRequest request) { // $ hasCsrfUnprotectedRequestType
return "post";
}
// BAD: Stapler web method parameter annotated with `@QueryParameter` and method name that implies a state-change
public String doPost5(@QueryParameter(value="user", fixEmpty=false, required=false) String user) { // $ hasCsrfUnprotectedRequestType
return "post";
}
// BAD: Stapler web method with declared exception type implementing HttpResponse and method name that implies a state-change
public String doPost6(String user) throws HttpResponses.HttpResponseException { // $ hasCsrfUnprotectedRequestType
return "post";
}
// BAD: Stapler web method with return type implementing HttpResponse and method name that implies a state-change
public HttpRedirect doPost7(String url) { // $ hasCsrfUnprotectedRequestType
HttpRedirect redirect = new HttpRedirect(url);
return redirect;
}
}

View File

@@ -0,0 +1,18 @@
import java
import semmle.code.java.security.CsrfUnprotectedRequestTypeQuery
import utils.test.InlineExpectationsTest
module CsrfUnprotectedRequestTypeTest implements TestSig {
string getARelevantTag() { result = "hasCsrfUnprotectedRequestType" }
predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "hasCsrfUnprotectedRequestType" and
exists(CallPathNode src | unprotectedStateChange(src, _) |
src.getLocation() = location and
element = src.toString() and
value = ""
)
}
}
import MakeTest<CsrfUnprotectedRequestTypeTest>

View File

@@ -0,0 +1,43 @@
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import org.apache.ibatis.annotations.DeleteProvider;
import org.apache.ibatis.annotations.UpdateProvider;
import org.apache.ibatis.annotations.InsertProvider;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Update;
import org.apache.ibatis.annotations.Insert;
@Mapper
@Repository
public interface MyBatisMapper {
void bad7(String name);
//using providers
@DeleteProvider(
type = MyBatisProvider.class,
method = "badDelete"
)
void badDelete(String input);
@UpdateProvider(
type = MyBatisProvider.class,
method = "badUpdate"
)
void badUpdate(String input);
@InsertProvider(
type = MyBatisProvider.class,
method = "badInsert"
)
void badInsert(String input);
@Delete("DELETE FROM users WHERE id = #{id}")
boolean bad8(int id);
@Insert("INSERT INTO users (id, name) VALUES(#{id}, #{name})")
void bad9(String user);
@Update("UPDATE users SET name = #{name} WHERE id = #{id}")
boolean bad10(String user);
}

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="MyBatisMapper">
<resultMap id="BaseResultMap" type="Test">
<id column="id" jdbcType="INTEGER" property="id"/>
<result column="name" jdbcType="VARCHAR" property="name"/>
<result column="pass" jdbcType="VARCHAR" property="pass"/>
</resultMap>
<sql id="Update_By_Example_Where_Clause">
<where>
<if test="test.name != null">
and name = ${ test . name , jdbcType = VARCHAR }
</if>
<if test="test.id != null">
and id = #{test.id}
</if>
</where>
</sql>
<insert id="bad7" parameterType="Test">
insert into test (name, pass)
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="name != null">
name = ${name,jdbcType=VARCHAR},
</if>
<if test="pass != null">
pass = ${pass},
</if>
</trim>
</insert>
</mapper>

View File

@@ -0,0 +1,24 @@
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.jdbc.SQL;
public class MyBatisProvider {
public String badDelete(@Param("input") final String input) {
return "DELETE FROM users WHERE username = '" + input + "';";
}
public String badUpdate(@Param("input") final String input) {
String s = (new SQL() {
{
this.UPDATE("users");
this.SET("balance = 0");
this.WHERE("username = '" + input + "'");
}
}).toString();
return s;
}
public String badInsert(@Param("input") final String input) {
return "INSERT INTO users VALUES (1, '" + input + "', 'hunter2');";
}
}

View File

@@ -0,0 +1,37 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class MyBatisService {
@Autowired
private MyBatisMapper myBatisMapper;
public void bad7(String name) {
myBatisMapper.bad7(name);
}
public void badDelete(String input) {
myBatisMapper.badDelete(input);
}
public void badUpdate(String input) {
myBatisMapper.badUpdate(input);
}
public void badInsert(String input) {
myBatisMapper.badInsert(input);
}
public void bad8(int id){
myBatisMapper.bad8(id);
}
public void bad9(String user){
myBatisMapper.bad9(user);
}
public void bad10(String user){
myBatisMapper.bad10(user);
}
}

View File

@@ -1 +1 @@
semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/springframework-5.3.8
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/springframework-5.3.8/:${testdir}/../../../stubs/org.mybatis-3.5.4/:${testdir}/../../../stubs/stapler-1.263/:${testdir}/../../../stubs/javax-servlet-2.5:${testdir}/../../../stubs/apache-commons-jelly-1.0.1:${testdir}/../../../stubs/apache-commons-fileupload-1.4:${testdir}/../../../stubs/saxon-xqj-9.x:${testdir}/../../../stubs/apache-commons-beanutils:${testdir}/../../../stubs/dom4j-2.1.1:${testdir}/../../../stubs/apache-commons-lang:${testdir}/../../../stubs/jaxen-1.2.0:${testdir}/../../../stubs/apache-commons-logging-1.2/

View File

@@ -0,0 +1,14 @@
package org.apache.ibatis.annotations;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Delete {
String[] value();
}

View File

@@ -0,0 +1,14 @@
package org.apache.ibatis.annotations;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Insert {
String[] value();
}

View File

@@ -0,0 +1,14 @@
package org.apache.ibatis.annotations;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Update {
String[] value();
}

View File

@@ -0,0 +1,37 @@
package org.apache.ibatis.jdbc;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
public class SqlRunner {
public static final int NO_GENERATED_KEY = Integer.MIN_VALUE + 1001;
private final Connection connection;
private boolean useGeneratedKeySupport;
public SqlRunner(Connection connection) {
this.connection = connection;
}
public void setUseGeneratedKeySupport(boolean useGeneratedKeySupport) { }
public Map<String, Object> selectOne(String sql, Object... args) throws SQLException { return null; }
public List<Map<String, Object>> selectAll(String sql, Object... args) throws SQLException { return null; }
public int insert(String sql, Object... args) throws SQLException { return 0; }
public int update(String sql, Object... args) throws SQLException { return 0; }
public int delete(String sql, Object... args) throws SQLException { return 0; }
public void closeConnection() { }
private void setParameters(PreparedStatement ps, Object... args) throws SQLException { }
private List<Map<String, Object>> getResults(ResultSet rs) throws SQLException { return null; }
}

View File

@@ -0,0 +1,169 @@
package org.springframework.jdbc.core.namedparam;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Stream;
import javax.sql.DataSource;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCallback;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.jdbc.support.rowset.SqlRowSet;
public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations {
public static final int DEFAULT_CACHE_LIMIT = 256;
private final JdbcOperations classicJdbcTemplate;
public NamedParameterJdbcTemplate(DataSource dataSource) {
this.classicJdbcTemplate = new JdbcTemplate(dataSource);
}
public NamedParameterJdbcTemplate(JdbcOperations classicJdbcTemplate) {
this.classicJdbcTemplate = classicJdbcTemplate;
}
@Override
public JdbcOperations getJdbcOperations() { return null; }
public JdbcTemplate getJdbcTemplate() { return null; }
public void setCacheLimit(int cacheLimit) { }
public int getCacheLimit() { return 0; }
@Override
public <T> T execute(String sql, SqlParameterSource paramSource, PreparedStatementCallback<T> action)
throws DataAccessException { return null; }
@Override
public <T> T execute(String sql, Map<String, ?> paramMap, PreparedStatementCallback<T> action)
throws DataAccessException { return null; }
@Override
public <T> T execute(String sql, PreparedStatementCallback<T> action) throws DataAccessException { return null; }
@Override
public <T> T query(String sql, SqlParameterSource paramSource, ResultSetExtractor<T> rse)
throws DataAccessException { return null; }
@Override
public <T> T query(String sql, Map<String, ?> paramMap, ResultSetExtractor<T> rse)
throws DataAccessException { return null; }
@Override
public <T> T query(String sql, ResultSetExtractor<T> rse) throws DataAccessException { return null; }
@Override
public void query(String sql, SqlParameterSource paramSource, RowCallbackHandler rch)
throws DataAccessException { }
@Override
public void query(String sql, Map<String, ?> paramMap, RowCallbackHandler rch)
throws DataAccessException { }
@Override
public void query(String sql, RowCallbackHandler rch) throws DataAccessException { }
@Override
public <T> List<T> query(String sql, SqlParameterSource paramSource, RowMapper<T> rowMapper)
throws DataAccessException { return null; }
@Override
public <T> List<T> query(String sql, Map<String, ?> paramMap, RowMapper<T> rowMapper)
throws DataAccessException { return null; }
@Override
public <T> List<T> query(String sql, RowMapper<T> rowMapper) throws DataAccessException { return null; }
@Override
public <T> Stream<T> queryForStream(String sql, SqlParameterSource paramSource, RowMapper<T> rowMapper)
throws DataAccessException { return null; }
@Override
public <T> Stream<T> queryForStream(String sql, Map<String, ?> paramMap, RowMapper<T> rowMapper)
throws DataAccessException { return null; }
@Override
public <T> T queryForObject(String sql, SqlParameterSource paramSource, RowMapper<T> rowMapper)
throws DataAccessException { return null; }
@Override
public <T> T queryForObject(String sql, Map<String, ?> paramMap, RowMapper<T>rowMapper)
throws DataAccessException { return null; }
@Override
public <T> T queryForObject(String sql, SqlParameterSource paramSource, Class<T> requiredType)
throws DataAccessException { return null; }
@Override
public <T> T queryForObject(String sql, Map<String, ?> paramMap, Class<T> requiredType)
throws DataAccessException { return null; }
@Override
public Map<String, Object> queryForMap(String sql, SqlParameterSource paramSource) throws DataAccessException { return null; }
@Override
public Map<String, Object> queryForMap(String sql, Map<String, ?> paramMap) throws DataAccessException { return null; }
@Override
public <T> List<T> queryForList(String sql, SqlParameterSource paramSource, Class<T> elementType)
throws DataAccessException { return null; }
@Override
public <T> List<T> queryForList(String sql, Map<String, ?> paramMap, Class<T> elementType)
throws DataAccessException { return null; }
@Override
public List<Map<String, Object>> queryForList(String sql, SqlParameterSource paramSource)
throws DataAccessException { return null; }
@Override
public List<Map<String, Object>> queryForList(String sql, Map<String, ?> paramMap)
throws DataAccessException { return null; }
@Override
public SqlRowSet queryForRowSet(String sql, SqlParameterSource paramSource) throws DataAccessException { return null; }
@Override
public SqlRowSet queryForRowSet(String sql, Map<String, ?> paramMap) throws DataAccessException { return null; }
@Override
public int update(String sql, SqlParameterSource paramSource) throws DataAccessException { return 0; }
@Override
public int update(String sql, Map<String, ?> paramMap) throws DataAccessException { return 0; }
@Override
public int update(String sql, SqlParameterSource paramSource, KeyHolder generatedKeyHolder)
throws DataAccessException { return 0; }
@Override
public int update(
String sql, SqlParameterSource paramSource, KeyHolder generatedKeyHolder, String[] keyColumnNames)
throws DataAccessException { return 0; }
@Override
public int[] batchUpdate(String sql, SqlParameterSource[] batchArgs) { return new int[0]; }
@Override
public int[] batchUpdate(String sql, Map<String, ?>[] batchValues) { return new int[0]; }
public int[] batchUpdate(String sql, SqlParameterSource[] batchArgs, KeyHolder generatedKeyHolder) { return new int[0]; }
public int[] batchUpdate(String sql, SqlParameterSource[] batchArgs, KeyHolder generatedKeyHolder,
String[] keyColumnNames) { return new int[0]; }
protected PreparedStatementCreator getPreparedStatementCreator(String sql, SqlParameterSource paramSource) {
return null;
}
protected ParsedSql getParsedSql(String sql) { return null; }
}

View File

@@ -0,0 +1,13 @@
// Generated automatically from org.kohsuke.stapler.AnnotationHandler for testing purposes
package org.kohsuke.stapler;
import java.lang.annotation.Annotation;
import org.kohsuke.stapler.StaplerRequest;
abstract public class AnnotationHandler<T extends Annotation>
{
protected final Object convert(Class p0, String p1){ return null; }
public AnnotationHandler(){}
public abstract Object parse(StaplerRequest p0, T p1, Class p2, String p3);
}

View File

@@ -0,0 +1,28 @@
// Generated automatically from org.kohsuke.stapler.QueryParameter for testing purposes
package org.kohsuke.stapler;
import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.kohsuke.stapler.AnnotationHandler;
import org.kohsuke.stapler.InjectedParameter;
import org.kohsuke.stapler.StaplerRequest;
@Documented
@Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value={java.lang.annotation.ElementType.PARAMETER})
public @interface QueryParameter
{
String value();
boolean fixEmpty();
boolean required();
static public class HandlerImpl extends AnnotationHandler<QueryParameter>
{
public HandlerImpl(){}
public Object parse(StaplerRequest p0, QueryParameter p1, Class p2, String p3){ return null; }
}
}

View File

@@ -0,0 +1,18 @@
// Generated automatically from org.kohsuke.stapler.WebMethod for testing purposes
package org.kohsuke.stapler;
import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Documented
@Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value={java.lang.annotation.ElementType.METHOD})
public @interface WebMethod
{
String[] name();
}

View File

@@ -0,0 +1,15 @@
// Generated automatically from org.kohsuke.stapler.interceptor.Interceptor for testing purposes
package org.kohsuke.stapler.interceptor;
import org.kohsuke.stapler.Function;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
abstract public class Interceptor
{
protected Function target = null;
public Interceptor(){}
public abstract Object invoke(StaplerRequest p0, StaplerResponse p1, Object p2, Object[] p3);
public void setTarget(Function p0){}
}

View File

@@ -0,0 +1,21 @@
// Generated automatically from org.kohsuke.stapler.interceptor.InterceptorAnnotation for testing purposes
package org.kohsuke.stapler.interceptor;
import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.kohsuke.stapler.interceptor.Interceptor;
import org.kohsuke.stapler.interceptor.Stage;
@Documented
@Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value={java.lang.annotation.ElementType.ANNOTATION_TYPE})
public @interface InterceptorAnnotation
{
Class<? extends Interceptor> value();
Stage stage();
}

View File

@@ -0,0 +1,25 @@
// Generated automatically from org.kohsuke.stapler.interceptor.RequirePOST for testing purposes
package org.kohsuke.stapler.interceptor;
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.interceptor.Interceptor;
import org.kohsuke.stapler.interceptor.InterceptorAnnotation;
import org.kohsuke.stapler.interceptor.Stage;
@Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value={java.lang.annotation.ElementType.METHOD,java.lang.annotation.ElementType.FIELD})
public @interface RequirePOST
{
static public class Processor extends Interceptor
{
public Object invoke(StaplerRequest p0, StaplerResponse p1, Object p2, Object[] p3){ return null; }
public Processor(){}
}
}

View File

@@ -0,0 +1,10 @@
// Generated automatically from org.kohsuke.stapler.interceptor.Stage for testing purposes
package org.kohsuke.stapler.interceptor;
public enum Stage
{
PREINVOKE, SELECTION;
private Stage() {}
}

View File

@@ -0,0 +1,19 @@
// Generated automatically from org.kohsuke.stapler.verb.GET for testing purposes
package org.kohsuke.stapler.verb;
import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.kohsuke.stapler.interceptor.InterceptorAnnotation;
import org.kohsuke.stapler.interceptor.Stage;
@Documented
@Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value={java.lang.annotation.ElementType.METHOD})
public @interface GET
{
}

View File

@@ -0,0 +1,19 @@
// Generated automatically from org.kohsuke.stapler.verb.POST for testing purposes
package org.kohsuke.stapler.verb;
import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.kohsuke.stapler.interceptor.InterceptorAnnotation;
import org.kohsuke.stapler.interceptor.Stage;
@Documented
@Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value={java.lang.annotation.ElementType.METHOD})
public @interface POST
{
}

View File

@@ -0,0 +1,19 @@
// Generated automatically from org.kohsuke.stapler.verb.PUT for testing purposes
package org.kohsuke.stapler.verb;
import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.kohsuke.stapler.interceptor.InterceptorAnnotation;
import org.kohsuke.stapler.interceptor.Stage;
@Documented
@Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value={java.lang.annotation.ElementType.METHOD})
public @interface PUT
{
}