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 final 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      private SchemaHolder() {
75      }
76    }
77  
78    @Intercepts(@Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class, Integer.class }))
79    public static class SwitchCatalogInterceptor implements Interceptor {
80      @Override
81      public Object intercept(Invocation invocation) throws Throwable {
82        Object[] args = invocation.getArgs();
83        Connection con = (Connection) args[0];
84        con.setSchema(SchemaHolder.get());
85        return invocation.proceed();
86      }
87    }
88  
89    @Test
90    void shouldPluginNotInvokeArbitraryMethod() {
91      Map<?, ?> map = new HashMap<>();
92      map = (Map<?, ?>) new AlwaysMapPlugin().plugin(map);
93      try {
94        map.get("Anything");
95        fail("Exected IllegalArgumentException, but no exception was thrown.");
96      } catch (IllegalArgumentException e) {
97        assertEquals(
98            "Method 'public abstract java.lang.Object java.util.Map.get(java.lang.Object)' is not supported as a plugin target.",
99            e.getMessage());
100     } catch (Exception e) {
101       fail("Exected IllegalArgumentException, but was " + e.getClass(), e);
102     }
103   }
104 
105   @Intercepts({ @Signature(type = Map.class, method = "get", args = { Object.class }) })
106   public static class AlwaysMapPlugin implements Interceptor {
107     @Override
108     public Object intercept(Invocation invocation) {
109       return "Always";
110     }
111   }
112 }