diff --git a/src/main/java/com/fanruan/api/design/ui/component/code/UISyntaxTextArea.java b/src/main/java/com/fanruan/api/design/ui/component/code/UISyntaxTextArea.java index bd1ea0f..478168a 100644 --- a/src/main/java/com/fanruan/api/design/ui/component/code/UISyntaxTextArea.java +++ b/src/main/java/com/fanruan/api/design/ui/component/code/UISyntaxTextArea.java @@ -8,14 +8,17 @@ import com.fr.design.gui.syntax.ui.rsyntaxtextarea.RSyntaxTextArea; * Created by richie on 2019-08-28 * 代码编辑器,支持javascript、sql、java、公式和普通文本 * @see com.fanruan.api.design.ui.component.code.SyntaxConstants - *

- * UISyntaxTextArea contentTextArea = new UISyntaxTextArea(); - * contentTextArea.setCloseCurlyBraces(true); - * contentTextArea.setLineWrap(true); - * contentTextArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT); - * contentTextArea.setCodeFoldingEnabled(true); - * contentTextArea.setAntiAliasingEnabled(true); - *

+ *
 {@code
+ *
+ *   UISyntaxTextArea contentTextArea = new UISyntaxTextArea();
+ *   contentTextArea.setCloseCurlyBraces(true);
+ *   contentTextArea.setLineWrap(true);
+ *
+ *   contentTextArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT);
+ *   contentTextArea.setCodeFoldingEnabled(true);
+ *   contentTextArea.setAntiAliasingEnabled(true);
+ * }
+ * 
*/ public class UISyntaxTextArea extends RSyntaxTextArea { diff --git a/src/main/java/com/fanruan/api/design/ui/layout/TableLayoutKit.java b/src/main/java/com/fanruan/api/design/ui/layout/TableLayoutKit.java index 6aaf056..fa2b661 100644 --- a/src/main/java/com/fanruan/api/design/ui/layout/TableLayoutKit.java +++ b/src/main/java/com/fanruan/api/design/ui/layout/TableLayoutKit.java @@ -11,18 +11,19 @@ import java.awt.*; * @version 10.0 * Created by richie on 2019-08-28 * 表格布局 - * - * double p = TableLayoutKit.PREFERRED; - * double f = TableLayoutKit.FILL; - * double[] rowSize = new double[]{p, p, p, f}; - * double[] columnSize = new double[]{p, f}; - * JComponent[][] comps = new JComponent[][]{ - * {new JLabel(), new JButton()}, - * {new JLabel(), new JButton()}, - * {new JLabel(), new JButton()} + *
 {@code
+ *   double p = TableLayoutKit.PREFERRED;
+ *   double f = TableLayoutKit.FILL;
+ *   double[] rowSize = new double[]{p, p, p, f};
+ *   double[] columnSize = new double[]{p, f};
+ *   JComponent[][] comps = new JComponent[][]{
+ *        {new JLabel(), new JButton()},
+ *        {new JLabel(), new JButton()},
+ *        {new JLabel(), new JButton()}
+ *   };
+ *   JPanel = TableLayoutKit.createTableLayoutPane(comps, rowSize, columnSize);
  * }
- * JPanel = TableLayoutKit.createTableLayoutPane(comps, rowSize, columnSize);
- * 
+ * 
*/ public class TableLayoutKit { diff --git a/src/main/java/com/fanruan/api/net/CloudKit.java b/src/main/java/com/fanruan/api/net/CloudKit.java new file mode 100644 index 0000000..775ea6e --- /dev/null +++ b/src/main/java/com/fanruan/api/net/CloudKit.java @@ -0,0 +1,36 @@ +package com.fanruan.api.net; + +import com.fr.general.CloudCenter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author richie + * @version 10.0 + * Created by richie on 2019-08-30 + * 云中心交互工具类 + */ +public class CloudKit { + + + /** + * 从云中心获取值 + * + * @param kind 键 + * @param defaultSiteUrl 默认值 + * @return 键对应的值,如果没有值则返回默认值 + */ + public @Nullable String acquireUrlByKind(@NotNull String kind, @NotNull String defaultSiteUrl) { + return CloudCenter.getInstance().acquireUrlByKind(kind, defaultSiteUrl); + } + + /** + * 从云中心获取值 + * + * @param kind 键 + * @return 键对应的值,如果没有值则返回空 + */ + public @Nullable String acquireUrlByKind(@NotNull String kind) { + return CloudCenter.getInstance().acquireUrlByKind(kind); + } +} diff --git a/src/test/java/com/fanruan/api/session/MockSession.java b/src/test/java/com/fanruan/api/session/MockSession.java new file mode 100644 index 0000000..0568c87 --- /dev/null +++ b/src/test/java/com/fanruan/api/session/MockSession.java @@ -0,0 +1,47 @@ +package com.fanruan.api.session; + +import com.fr.stable.script.CalculatorProvider; +import com.fr.stable.web.WebContextProvider; +import com.fr.web.session.SessionIDInfo; + +/** + * @author richie + * @version 10.0 + * Created by richie on 2019-08-30 + */ +class MockSession extends SessionIDInfo { + + MockSession(String sessionID) { + this.sessionID = sessionID; + } + + @Override + public String getWebTitle() { + return null; + } + + @Override + public String getRelativePath() { + return null; + } + + @Override + public WebContextProvider getWebContext() { + return null; + } + + @Override + public Object resolveVariable(Object var, CalculatorProvider cal) { + return null; + } + + @Override + public Object getParameterValue(String parameterName) { + return null; + } + + @Override + public void release() { + + } +} diff --git a/src/test/java/com/fanruan/api/session/SessionKitTest.java b/src/test/java/com/fanruan/api/session/SessionKitTest.java index 3e486cb..275d52d 100644 --- a/src/test/java/com/fanruan/api/session/SessionKitTest.java +++ b/src/test/java/com/fanruan/api/session/SessionKitTest.java @@ -1,18 +1,186 @@ package com.fanruan.api.session; import com.fanruan.api.Prepare; +import com.fr.general.web.ParameterConstants; +import com.fr.invoke.Reflect; +import com.fr.stable.StringUtils; +import com.fr.stable.web.SessionProvider; +import com.fr.stable.web.SessionSource; +import com.fr.stable.web.Weblet; +import com.fr.web.core.RemoteAddressManager; +import com.fr.web.core.SessionPoolManager; +import com.fr.web.session.SessionIDInfo; +import com.fr.web.utils.WebUtils; +import org.easymock.EasyMock; +import org.easymock.IAnswer; +import org.easymock.IMocksControl; import org.junit.Assert; import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.api.easymock.PowerMock; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.reflect.Whitebox; + +import javax.servlet.http.HttpServletRequest; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; /** * @author richie * @version 10.0 * Created by richie on 2019-08-09 */ +@RunWith(PowerMockRunner.class) +@PrepareForTest({SessionPoolManager.class, WebUtils.class}) +@SuppressStaticInitializationFor({"com.fr.web.core.SessionPoolManager"}) public class SessionKitTest extends Prepare { + private static final long MIN_ACCESS_INTERVAL = 900; + private int taskCount = 0; + private Map sessions = new HashMap(); + + @Test + public void testGenerateSession() throws Exception { + final SessionIDInfo sessionInfo = new MockSession("session"); + final Map params = new HashMap(); + PowerMock.mockStatic(SessionPoolManager.class); + PowerMock.mockStatic(WebUtils.class); + IMocksControl control = EasyMock.createControl(); + final HttpServletRequest request = control.createMock(HttpServletRequest.class); + EasyMock.expect(WebUtils.getIpAddr(request)).andReturn("127.0.0.1").anyTimes(); + EasyMock.expect(WebUtils.getHTTPRequestParameter(request, ParameterConstants.OP)).andReturn("view").anyTimes(); + EasyMock.expect(WebUtils.parameters4SessionIDInforContainMPCache(request)).andReturn(params).anyTimes(); + final Weblet weblet = control.createMock(Weblet.class); + EasyMock.expect(weblet.isSessionOccupy()).andReturn(false).anyTimes(); + EasyMock.expect(weblet.createSessionIDInfor(request, "127.0.0.1", params)).andReturn(sessionInfo).anyTimes(); + EasyMock.expect(addSessionIDInfo(sessionInfo)).andReturn(sessionInfo.getSessionID()).anyTimes(); + EasyMock.expect(SessionPoolManager.generateSessionID(request, null, weblet)).andAnswer(new IAnswer() { + @Override + public String answer() throws Throwable { + SessionProvider sessionIDInfor = weblet.createSessionIDInfor(request, "127.0.0.1", params); + String sessionID = addSessionIDInfo(sessionIDInfor); + if (weblet.isSessionOccupy()) { + assert sessionID != null; + RemoteAddressManager.add("127.0.0.1", sessionID); + } + return sessionID; + } + }).anyTimes(); + control.replay(); + PowerMock.replayAll(); + sessionInfo.setSource(SessionSource.SINGLE); + SessionPoolManager.generateSessionID(request, null, weblet); + Assert.assertSame(sessionInfo.getSource(), SessionSource.SINGLE); + sessionInfo.setSource(SessionSource.INTEGRATION); + SessionPoolManager.generateSessionID(request, null, weblet); + Assert.assertSame(sessionInfo.getSource(), SessionSource.INTEGRATION); + + } + + @Test + public void testAddDelayTask() { + String sessionID = "test"; + sessions.put("test", new MockSession("test")); + for (int i = 0; i < 100; i++) { + accessSession(sessionID); + } + Assert.assertEquals(1, this.taskCount); + for (int i = 0; i < 2; i++) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + //do nothing + } + accessSession(sessionID); + } + Assert.assertEquals(3, this.taskCount); + } + + private void accessSession(String sessionId) { + if (StringUtils.isBlank(sessionId)) { + return; + } + + SessionProvider sessionIDInfor = sessions.get(sessionId); + if (sessionIDInfor != null) { + long accessInterval = System.currentTimeMillis() - sessionIDInfor.getLastAccessTime(); + sessionIDInfor.updateTime(); + if (accessInterval > MIN_ACCESS_INTERVAL) { + taskCount++; + } + } + } + + @Test + public void testGetAllSession() { + Whitebox.setInternalState( + SessionPoolManager.class, + "sessionIDMap", + new ConcurrentHashMap() + ); + Whitebox.setInternalState(SessionPoolManager.class, "sessionToDelete", new HashSet()); + Map sessionIDMap = Reflect.on(SessionPoolManager.class).get("sessionIDMap"); + String sessionID1 = "Test1"; + sessionIDMap.put(sessionID1, new MockSession(sessionID1)); + sessionIDMap.put("Test2", new MockSession("Test2")); + closeSession(sessionID1); + List list = SessionPoolManager.getAllSession(SessionProvider.class); + assertEquals(1, list.size()); + assertEquals("Test2", list.get(0).getSessionID()); + assertNotNull(SessionKit.getSession("Test2")); + } + @Test - public void getSession() throws Exception { - Assert.assertNull(SessionKit.getSession("abc")); + public void testHasSessionID() { + Whitebox.setInternalState( + SessionPoolManager.class, + "sessionIDMap", + new ConcurrentHashMap() + ); + Whitebox.setInternalState(SessionPoolManager.class, "sessionToDelete", new HashSet()); + Map sessionIDMap = Reflect.on(SessionPoolManager.class).get("sessionIDMap"); + String sessionID1 = "Test1"; + sessionIDMap.put(sessionID1, new MockSession(sessionID1)); + sessionIDMap.put("Test2", new MockSession("Test2")); + closeSession(sessionID1); + assertFalse(SessionPoolManager.hasSessionID(sessionID1)); + assertTrue(SessionPoolManager.hasSessionID("Test2")); + } + + private void closeSession(final String sessionID) { + final Set sessionToDelete = Reflect.on(SessionPoolManager.class).get("sessionToDelete"); + sessionToDelete.add(sessionID); + ExecutorService closeSessionPool = Executors.newFixedThreadPool(1); + closeSessionPool.submit(new Runnable() { + @Override + public void run() { + try { + //模拟删除session对象的过程 + Thread.sleep(1000); + } catch (InterruptedException e) { + //do nothing + } + synchronized (SessionPoolManager.class) { + sessionToDelete.remove(sessionID); + } + } + }); + } + + private String addSessionIDInfo(SessionProvider sessionIDInfo) { + return Reflect.on(SessionPoolManager.class).call("addSessionIDInfor", sessionIDInfo).get(); } } \ No newline at end of file