View Javadoc
1   /*
2    *    Copyright 2009-2024 the original author or authors.
3    *
4    *    Licensed under the Apache License, Version 2.0 (the "License");
5    *    you may not use this file except in compliance with the License.
6    *    You may obtain a copy of the License at
7    *
8    *       https://www.apache.org/licenses/LICENSE-2.0
9    *
10   *    Unless required by applicable law or agreed to in writing, software
11   *    distributed under the License is distributed on an "AS IS" BASIS,
12   *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *    See the License for the specific language governing permissions and
14   *    limitations under the License.
15   */
16  package org.apache.ibatis.plugin;
17  
18  import static org.junit.jupiter.api.Assertions.assertEquals;
19  import static org.junit.jupiter.api.Assertions.fail;
20  
21  import java.io.Reader;
22  import java.sql.Connection;
23  import java.util.HashMap;
24  import java.util.Map;
25  
26  import org.apache.ibatis.BaseDataTest;
27  import org.apache.ibatis.executor.statement.StatementHandler;
28  import org.apache.ibatis.io.Resources;
29  import org.apache.ibatis.session.SqlSession;
30  import org.apache.ibatis.session.SqlSessionFactory;
31  import org.apache.ibatis.session.SqlSessionFactoryBuilder;
32  import org.junit.jupiter.api.BeforeAll;
33  import org.junit.jupiter.api.Test;
34  
35  class PluginTest {
36  
37    private static SqlSessionFactory sqlSessionFactory;
38  
39    @BeforeAll
40    static void setUp() throws Exception {
41      try (Reader reader = Resources.getResourceAsReader("org/apache/ibatis/plugin/mybatis-config.xml")) {
42        sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
43      }
44      BaseDataTest.runScript(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(),
45          "org/apache/ibatis/plugin/CreateDB.sql");
46    }
47  
48    @Test
49    void shouldPluginSwitchSchema() {
50      try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
51        Mapper mapper = sqlSession.getMapper(Mapper.class);
52        assertEquals("Public user 1", mapper.selectNameById(1));
53      }
54  
55      SchemaHolder.set("MYSCHEMA");
56  
57      try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
58        Mapper mapper = sqlSession.getMapper(Mapper.class);
59        assertEquals("Private user 1", mapper.selectNameById(1));
60      }
61    }
62  
63    static class SchemaHolder {
64      private static ThreadLocal<String> value = ThreadLocal.withInitial(() -> "PUBLIC");
65  
66      public static void set(String tenantName) {
67        value.set(tenantName);
68      }
69  
70      public static String get() {
71        return value.get();
72      }
73    }
74  
75    @Intercepts(@Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class, Integer.class }))
76    public static class SwitchCatalogInterceptor implements Interceptor {
77      @Override
78      public Object intercept(Invocation invocation) throws Throwable {
79        Object[] args = invocation.getArgs();
80        Connection con = (Connection) args[0];
81        con.setSchema(SchemaHolder.get());
82        return invocation.proceed();
83      }
84    }
85  
86    @Test
87    void shouldPluginNotInvokeArbitraryMethod() {
88      Map<?, ?> map = new HashMap<>();
89      map = (Map<?, ?>) new AlwaysMapPlugin().plugin(map);
90      try {
91        map.get("Anything");
92        fail("Exected IllegalArgumentException, but no exception was thrown.");
93      } catch (IllegalArgumentException e) {
94        assertEquals(
95            "Method 'public abstract java.lang.Object java.util.Map.get(java.lang.Object)' is not supported as a plugin target.",
96            e.getMessage());
97      } catch (Exception e) {
98        fail("Exected IllegalArgumentException, but was " + e.getClass(), e);
99      }
100   }
101 
102   @Intercepts({ @Signature(type = Map.class, method = "get", args = { Object.class }) })
103   public static class AlwaysMapPlugin implements Interceptor {
104     @Override
105     public Object intercept(Invocation invocation) {
106       return "Always";
107     }
108   }
109 }