Browse Source

init

master
yaoh.wu 5 years ago
commit
4320f572d5
  1. 4
      .gitignore
  2. 117
      build.xml
  3. 0
      lib/.keep
  4. 0
      lib/report/.gitkeep
  5. 23
      plugin.xml
  6. 92
      pom.xml
  7. 36
      readme.md
  8. 20
      src/main/java/com/fr/plugin/cluster/req/demo/ClusterLockManager.java
  9. 34
      src/main/java/com/fr/plugin/cluster/req/demo/ReqDemoHandler.java
  10. 73
      src/main/java/com/fr/plugin/cluster/req/demo/ReqDemoManager.java
  11. 74
      src/main/java/com/fr/plugin/cluster/req/demo/TaskInfoManager.java
  12. 8
      src/main/java/com/fr/plugin/cluster/req/demo/URIConstants.java
  13. 33
      src/main/java/com/fr/plugin/cluster/req/demo/cluster/ClusterReqDemoForwardProvider.java
  14. 17
      src/main/java/com/fr/plugin/cluster/req/demo/entity/Task.java
  15. 52
      src/main/java/com/fr/plugin/cluster/req/demo/handler/CreateAction.java
  16. 52
      src/main/java/com/fr/plugin/cluster/req/demo/handler/SearchAction.java
  17. 43
      src/main/java/com/fr/plugin/cluster/req/demo/handler/ViewAction.java
  18. 35
      src/main/java/com/fr/plugin/cluster/req/demo/url/ReqDemoUrlProvider.java

4
.gitignore vendored

@ -0,0 +1,4 @@
*.iml
.idea/
out/
target/

117
build.xml

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project basedir="." default="jar" name="plugin">
<!-- JDK路径,根据自己机器上实际位置修改-->
<property name="jdk.home" value="C:\Program Files\Java\jdk1.8.0_171"/>
<property name="libs" value="${basedir}/lib"/>
<property name="publicLibs" value=""/>
<property name="destLoc" value="."/>
<property name="classes" value="classes"/>
<xmlproperty file="${basedir}/plugin.xml"/>
<property name="current-version" value="${plugin.version}"/>
<!-- 插件版本-->
<property name="plugin-version" value="${current-version}"/>
<!-- 插件名字-->
<property name="plugin-name" value="excel-submit"/>
<property name="plugin-jar" value="fr-plugin-${plugin-name}-${plugin-version}.jar"/>
<target name="prepare">
<delete dir="${classes}"/>
<delete dir="fr-plugin-${plugin-name}-${plugin-version}"/>
<xmlproperty file="${basedir}/plugin.xml"/>
<delete dir="${destLoc}/${plugin.name}"/>
</target>
<path id="compile.classpath">
<fileset dir="${libs}">
<include name="**/*.jar"/>
</fileset>
<fileset dir="${publicLibs}">
<include name="**/*.jar"/>
</fileset>
</path>
<patternset id="resources4Jar">
<exclude name="**/.settings/**"/>
<exclude name=".classpath"/>
<exclude name=".project"/>
<exclude name="**/*.java"/>
<exclude name="**/*.db"/>
<exclude name="**/*.g"/>
<exclude name="**/package.html"/>
</patternset>
<target name="copy_resources">
<echo message="从${resources_from}拷贝图片,JS,CSS等资源文件"/>
<delete dir="tmp"/>
<copy todir="tmp">
<fileset dir="${resources_from}/src/main/resources">
<patternset refid="resources4Jar"/>
</fileset>
</copy>
<copy todir="${classes}">
<fileset dir="tmp"/>
</copy>
<delete dir="tmp"/>
</target>
<target name="compile_javas">
<echo message="编译${compile_files}下的Java文件"/>
<javac destdir="${classes}" debug="false" optimize="on" source="${source_jdk_version}"
target="${target_jdk_version}"
fork="true" memoryMaximumSize="512m" listfiles="false" srcdir="${basedir}"
executable="${compile_jdk_version}/bin/javac">
<src path="${basedir}/src/main/java"/>
<exclude name="**/.svn/**"/>
<compilerarg line="-encoding UTF8 "/>
<classpath refid="compile.classpath"/>
</javac>
</target>
<target name="jar_classes">
<echo message="打Jar包:${jar_name}"/>
<delete file="${basedir}/${jar_name}"/>
<jar jarfile="${basedir}/${jar_name}">
<fileset dir="${classes}">
</fileset>
</jar>
</target>
<target name="super_jar" depends="prepare">
<antcall target="copy_resources">
<param name="resources_from" value="${basedir}"/>
</antcall>
<antcall target="compile_javas">
<param name="source_jdk_version" value="1.6"/>
<param name="target_jdk_version" value="1.6"/>
<param name="compile_jdk_version" value="${jdk.home}"/>
<param name="compile_files" value="${basedir}/src"/>
</antcall>
<echo message="compile plugin success!"/>
<antcall target="jar_classes">
<param name="jar_name" value="${plugin-jar}"/>
</antcall>
<delete dir="${classes}"/>
</target>
<target name="jar" depends="super_jar">
<antcall target="zip"/>
</target>
<target name="zip">
<property name="plugin-folder" value="fr-plugin-${plugin-name}-${plugin-version}"/>
<echo message="----------zip files----------"/>
<mkdir dir="${plugin-folder}"/>
<copy todir="${plugin-folder}">
<fileset dir=".">
<include name="${plugin-jar}"/>
<include name="plugin.xml"/>
</fileset>
</copy>
<zip destfile="${basedir}/${plugin-folder}.zip" basedir=".">
<include name="${plugin-folder}/*.jar"/>
<include name="${plugin-folder}/plugin.xml"/>
</zip>
<xmlproperty file="${basedir}/plugin.xml"/>
<move file="${plugin-folder}.zip" todir="${destLoc}/${plugin.name}"/>
</target>
</project>

0
lib/report/.gitkeep

23
plugin.xml

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<plugin>
<id>com.fr.plugin.cluster.req.demo</id>
<name><![CDATA[集群转发插件demo]]></name>
<active>yes</active>
<hidden>no</hidden>
<version>1.0.0</version>
<env-version>10.0~</env-version>
<jartime>2019-07-30</jartime>
<vendor>finereport.yaohwu</vendor>
<description><![CDATA[集群转发插件demo]]></description>
<change-notes><![CDATA[
[2019-07-29]demo<br/>
]]></change-notes>
<function-recorder class="com.fr.plugin.cluster.req.demo.ReqDemoManager"/>
<extra-core>
<ClusterForwardProvider class="com.fr.plugin.cluster.req.demo.cluster.ClusterReqDemoForwardProvider"/>
</extra-core>
<extra-decision>
<HttpHandlerProvider class="com.fr.plugin.cluster.req.demo.ReqDemoHandler"/>
<URLAliasProvider class="com.fr.plugin.cluster.req.demo.url.ReqDemoUrlProvider"/>
</extra-decision>
</plugin>

92
pom.xml

@ -0,0 +1,92 @@
<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.fr.plugin</groupId>
<artifactId>plugin-cluster-req-demo</artifactId>
<version>10.0-RELEASE-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jdk.version>1.8</jdk.version>
<plugin-web-inf-path>
<!--依据插件实际安装位置修改-->
E:\FineCode\bugfix-core-10.0\webroot\WEB-INF\plugins\plugin-com.fr.plugin.cluster.req.demo-1.0.0
</plugin-web-inf-path>
</properties>
<dependencies>
<!--单元测试用开始-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<version>3.5.1</version>
<scope>test</scope>
</dependency>
<!--单元测试用结束-->
<dependency>
<groupId>com.fr.decision</groupId>
<artifactId>decision-feature</artifactId>
<version>10.0</version>
</dependency>
<dependency>
<groupId>com.fr.report</groupId>
<artifactId>engine</artifactId>
<version>10.0</version>
</dependency>
<dependency>
<groupId>com.fr.decision</groupId>
<artifactId>decision-report-feature</artifactId>
<version>10.0</version>
</dependency>
<dependency>
<groupId>com.fr.webui</groupId>
<artifactId>fine-webui</artifactId>
<version>10.0-RELEASE-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.7</version>
</dependency>
<dependency>
<groupId>com.fr.third</groupId>
<artifactId>fine-third</artifactId>
<version>10.0-RELEASE-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.fr.third.server</groupId>
<artifactId>servlet-api</artifactId>
<version>3.0</version>
</dependency>
<dependency>
<groupId>com.fr.third.driver</groupId>
<artifactId>ojdbc</artifactId>
<version>14</version>
</dependency>
</dependencies>
<build>
<outputDirectory>${plugin-web-inf-path}/classes</outputDirectory>
<testOutputDirectory>${plugin-web-inf-path}/test-classes</testOutputDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<proc>none</proc>
</configuration>
</plugin>
</plugins>
</build>
</project>

36
readme.md

@ -0,0 +1,36 @@
# ClusterForwardProvider 接口 demo
demo 插件中提供了三个接口:
1. /req/demo/create
2. /req/demo/search
3. /req/demo/view
search 接口需要携带 create 接口返回的id;
携带了 id 参数的search 请求总是会被转发到生成该 id 的节点,即处理前一个 create 请求的节点上。
浏览器中访问 http://host:port/webroot/decision/url/req/demo/create 得到返回值,其中有 id:
```json
{
"id": "4da3ca4a-9bb9-5116-dbaf-3d005fc4cab9",
"isCluster": true,
"clusterId": "M+n28J6oNcJMRUJhC+UczHLb2t1xQWXk2jqx2HHpGu3smaPzPw6DDQ==",
"taskName": "4da3ca4a-9bb9-5116-dbaf-3d005fc4cab9M+n28J6oNcJMRUJhC+UczHLb2t1xQWXk2jqx2HHpGu3smaPzPw6DDQ=="
}
```
该请求被集群转发策略,例如随机转发或者智能转发,转发到了节点 M+n28J6oNcJMRUJhC+UczHLb2t1xQWXk2jqx2HHpGu3smaPzPw6DDQ== 上;
后续浏览器访问 http://host:port/webroot/decision/url/req/demo/search?id=4da3ca4a-9bb9-5116-dbaf-3d005fc4cab9
的请求也会被转发到节点 M+n28J6oNcJMRUJhC+UczHLb2t1xQWXk2jqx2HHpGu3smaPzPw6DDQ==,返回值如下:
```json
{
"id": "4da3ca4a-9bb9-5116-dbaf-3d005fc4cab9",
"isCluster": true,
"clusterId": "M+n28J6oNcJMRUJhC+UczHLb2t1xQWXk2jqx2HHpGu3smaPzPw6DDQ==",
"taskName": "4da3ca4a-9bb9-5116-dbaf-3d005fc4cab9M+n28J6oNcJMRUJhC+UczHLb2t1xQWXk2jqx2HHpGu3smaPzPw6DDQ=="
}
```
而浏览器中访问 http://host:port/webroot/decision/url/req/demo/view 的请求会被代理例如 nginx 随机转发到某一节点。

20
src/main/java/com/fr/plugin/cluster/req/demo/ClusterLockManager.java

@ -0,0 +1,20 @@
package com.fr.plugin.cluster.req.demo;
import com.fr.cluster.ClusterBridge;
import com.fr.cluster.lock.ClusterLock;
import com.fr.cluster.lock.ClusterLockFactory;
public class ClusterLockManager {
private ClusterLockManager() {
}
/**
* 获取锁
*
* @return 集群锁
*/
public static ClusterLock getLock() {
ClusterLockFactory factory = ClusterBridge.getLockFactory();
return factory.get(ClusterLockManager.class);
}
}

34
src/main/java/com/fr/plugin/cluster/req/demo/ReqDemoHandler.java

@ -0,0 +1,34 @@
package com.fr.plugin.cluster.req.demo;
import com.fr.decision.fun.HttpHandler;
import com.fr.decision.fun.impl.AbstractAuthorityExpandTypesProvider;
import com.fr.decision.fun.impl.AbstractHttpHandlerProvider;
import com.fr.plugin.cluster.req.demo.handler.CreateAction;
import com.fr.plugin.cluster.req.demo.handler.SearchAction;
import com.fr.plugin.cluster.req.demo.handler.ViewAction;
import com.fr.stable.fun.mark.API;
/**
*
*/
@API(level = AbstractAuthorityExpandTypesProvider.CURRENT_LEVEL)
public class ReqDemoHandler extends AbstractHttpHandlerProvider {
@Override
public HttpHandler[] registerHandlers() {
return new HttpHandler[]{
new CreateAction(),
new SearchAction(),
new ViewAction()
};
}
@Override
public int currentAPILevel() {
return CURRENT_LEVEL;
}
@Override
public String mark4Provider() {
return getClass().getName();
}
}

73
src/main/java/com/fr/plugin/cluster/req/demo/ReqDemoManager.java

@ -0,0 +1,73 @@
package com.fr.plugin.cluster.req.demo;
import com.fr.cluster.lock.ClusterLock;
import com.fr.plugin.cluster.req.demo.entity.Task;
import com.fr.plugin.transform.ExecuteFunctionRecord;
import com.fr.plugin.transform.FunctionRecorder;
import com.fr.stable.StringUtils;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@FunctionRecorder
public class ReqDemoManager {
/**
* 本机所有处理中的任务
*/
private static final Map<String, Task> PROCESSES = new ConcurrentHashMap<String, Task>();
private ReqDemoManager() {
}
private static ClusterLock getLock() {
return ClusterLockManager.getLock();
}
@ExecuteFunctionRecord
public static void removeTask(String id) throws Exception {
ClusterLock lock = getLock();
try {
lock.lock();
if (id == null) {
return;
}
TaskInfoManager.removeTask(id);
PROCESSES.remove(id);
} finally {
lock.unlock();
}
}
public static Task getTask(String id) throws Exception {
if (id == null) {
return null;
}
ClusterLock lock = getLock();
try {
lock.lock();
return PROCESSES.get(id);
} finally {
lock.unlock();
}
}
public static void addTask(String id, Task task) throws Exception {
if (StringUtils.isBlank(id) || task == null) {
return;
}
ClusterLock lock = getLock();
try {
lock.lock();
TaskInfoManager.addTask(id);
PROCESSES.put(id, task);
} finally {
lock.unlock();
}
}
}

74
src/main/java/com/fr/plugin/cluster/req/demo/TaskInfoManager.java

@ -0,0 +1,74 @@
package com.fr.plugin.cluster.req.demo;
import com.fr.cluster.lock.ClusterLock;
import com.fr.log.FineLoggerFactory;
import com.fr.store.StateHubManager;
import com.fr.store.StateHubService;
import com.fr.web.core.ClusterShareInfo;
import com.fr.web.core.cluster.ClusterStatusHelper;
public class TaskInfoManager {
private static final String KEY = "ReqDemoTaskInfoPool";
private TaskInfoManager() {
}
/**
* 向队列中添加一个列表
*
* @param id 任务id
* @throws Exception 异常
*/
public static void addTask(String id) throws Exception {
ClusterLock lock = getLock();
try {
lock.lock();
StateHubService stateHubService = StateHubManager.applyForService(KEY);
stateHubService.put(id, new ClusterShareInfo(id, ClusterStatusHelper.getCurrentNodeId()));
} finally {
lock.unlock();
}
}
public static void removeTask(String id) throws Exception {
ClusterLock lock = getLock();
try {
lock.lock();
StateHubService stateHubService = StateHubManager.applyForService(KEY);
stateHubService.delete(id);
} finally {
lock.unlock();
}
}
public static String getTargetNodeId(String id) {
ClusterLock lock = getLock();
try {
lock.lock();
StateHubService stateHubService = StateHubManager.applyForService(KEY);
ClusterShareInfo info = stateHubService.get(id);
if (info != null) {
return info.getNodeID();
} else {
FineLoggerFactory.getLogger().debug("process cluster share info not found");
return null;
}
} catch (Exception e) {
FineLoggerFactory.getLogger().debug("occur exception while finding process cluster share info", e);
return null;
} finally {
lock.unlock();
}
}
/**
* 获取锁(集群时就是集群锁非集群时返回的是单机的)
*
* @return 集群锁
*/
private static ClusterLock getLock() {
return ClusterLockManager.getLock();
}
}

8
src/main/java/com/fr/plugin/cluster/req/demo/URIConstants.java

@ -0,0 +1,8 @@
package com.fr.plugin.cluster.req.demo;
public class URIConstants {
public static final String CREATE = "/req/demo/create";
public static final String SEARCH = "/req/demo/search";
public static final String VIEW = "/req/demo/view";
}

33
src/main/java/com/fr/plugin/cluster/req/demo/cluster/ClusterReqDemoForwardProvider.java

@ -0,0 +1,33 @@
package com.fr.plugin.cluster.req.demo.cluster;
import com.fr.plugin.cluster.req.demo.TaskInfoManager;
import com.fr.plugin.cluster.req.demo.URIConstants;
import com.fr.stable.fun.impl.AbstractClusterForwardProvider;
import com.fr.web.utils.WebUtils;
import org.jetbrains.annotations.Nullable;
import javax.servlet.http.HttpServletRequest;
public class ClusterReqDemoForwardProvider extends AbstractClusterForwardProvider {
@Override
public boolean needCreate(HttpServletRequest request) {
String requestUri = request.getRequestURI();
return requestUri.contains(URIConstants.CREATE);
}
@Override
public @Nullable String getTargetNodeID(String key) {
return TaskInfoManager.getTargetNodeId(key);
}
@Override
public String getKey(HttpServletRequest request) {
return WebUtils.getHTTPRequestParameter(request, "id");
}
@Override
public boolean accept(HttpServletRequest request) {
String requestUri = request.getRequestURI();
return requestUri.contains(URIConstants.CREATE) || requestUri.contains(URIConstants.SEARCH);
}
}

17
src/main/java/com/fr/plugin/cluster/req/demo/entity/Task.java

@ -0,0 +1,17 @@
package com.fr.plugin.cluster.req.demo.entity;
public class Task {
private String name;
public Task(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

52
src/main/java/com/fr/plugin/cluster/req/demo/handler/CreateAction.java

@ -0,0 +1,52 @@
package com.fr.plugin.cluster.req.demo.handler;
import com.fr.decision.fun.impl.BaseHttpHandler;
import com.fr.json.JSONObject;
import com.fr.plugin.cluster.req.demo.ReqDemoManager;
import com.fr.plugin.cluster.req.demo.URIConstants;
import com.fr.plugin.cluster.req.demo.entity.Task;
import com.fr.third.jgroups.util.UUID;
import com.fr.third.springframework.web.bind.annotation.RequestMethod;
import com.fr.web.core.cluster.ClusterStatusHelper;
import com.fr.web.utils.WebUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
*/
public class CreateAction extends BaseHttpHandler {
@Override
public RequestMethod getMethod() {
return RequestMethod.GET;
}
@Override
public String getPath() {
return URIConstants.CREATE;
}
@Override
public boolean isPublic() {
return true;
}
@Override
public void handle(HttpServletRequest req, HttpServletResponse res) throws Exception {
JSONObject json = new JSONObject();
String id = UUID.randomUUID().toString();
json.put("id", id);
boolean isCluster = ClusterStatusHelper.isClusterEnv();
json.put("isCluster", isCluster);
if (isCluster) {
String clusterNodeId = ClusterStatusHelper.getCurrentNodeId();
json.put("clusterId", clusterNodeId);
String taskName = id + clusterNodeId;
ReqDemoManager.addTask(id, new Task(taskName));
json.put("taskName", taskName);
}
WebUtils.printAsJSON(res, json);
}
}

52
src/main/java/com/fr/plugin/cluster/req/demo/handler/SearchAction.java

@ -0,0 +1,52 @@
package com.fr.plugin.cluster.req.demo.handler;
import com.fr.decision.fun.impl.BaseHttpHandler;
import com.fr.json.JSONObject;
import com.fr.plugin.cluster.req.demo.ReqDemoManager;
import com.fr.plugin.cluster.req.demo.URIConstants;
import com.fr.plugin.cluster.req.demo.entity.Task;
import com.fr.third.springframework.web.bind.annotation.RequestMethod;
import com.fr.web.core.cluster.ClusterStatusHelper;
import com.fr.web.utils.WebUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
*/
public class SearchAction extends BaseHttpHandler {
@Override
public RequestMethod getMethod() {
return RequestMethod.GET;
}
@Override
public String getPath() {
return URIConstants.SEARCH;
}
@Override
public boolean isPublic() {
return true;
}
@Override
public void handle(HttpServletRequest req, HttpServletResponse res) throws Exception {
JSONObject json = new JSONObject();
String id = WebUtils.getHTTPRequestParameter(req, "id");
json.put("id", id);
boolean isCluster = ClusterStatusHelper.isClusterEnv();
json.put("isCluster", isCluster);
if (isCluster) {
String clusterNodeId = ClusterStatusHelper.getCurrentNodeId();
json.put("clusterId", clusterNodeId);
Task task = ReqDemoManager.getTask(id);
if (task != null) {
json.put("taskName", task.getName());
}
}
WebUtils.printAsJSON(res, json);
}
}

43
src/main/java/com/fr/plugin/cluster/req/demo/handler/ViewAction.java

@ -0,0 +1,43 @@
package com.fr.plugin.cluster.req.demo.handler;
import com.fr.decision.fun.impl.BaseHttpHandler;
import com.fr.json.JSONObject;
import com.fr.plugin.cluster.req.demo.URIConstants;
import com.fr.third.springframework.web.bind.annotation.RequestMethod;
import com.fr.web.core.cluster.ClusterStatusHelper;
import com.fr.web.utils.WebUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
*/
public class ViewAction extends BaseHttpHandler {
@Override
public RequestMethod getMethod() {
return RequestMethod.GET;
}
@Override
public String getPath() {
return URIConstants.VIEW;
}
@Override
public boolean isPublic() {
return true;
}
@Override
public void handle(HttpServletRequest req, HttpServletResponse res) throws Exception {
JSONObject json = new JSONObject();
boolean isCluster = ClusterStatusHelper.isClusterEnv();
json.put("isCluster", isCluster);
if (isCluster) {
String clusterNodeId = ClusterStatusHelper.getCurrentNodeId();
json.put("clusterId", clusterNodeId);
}
WebUtils.printAsJSON(res, json);
}
}

35
src/main/java/com/fr/plugin/cluster/req/demo/url/ReqDemoUrlProvider.java

@ -0,0 +1,35 @@
package com.fr.plugin.cluster.req.demo.url;
import com.fr.decision.fun.impl.AbstractURLAliasProvider;
import com.fr.decision.webservice.url.alias.URLAlias;
import com.fr.decision.webservice.url.alias.URLAliasFactory;
import com.fr.stable.fun.mark.API;
import static com.fr.plugin.cluster.req.demo.URIConstants.CREATE;
import static com.fr.plugin.cluster.req.demo.URIConstants.SEARCH;
import static com.fr.plugin.cluster.req.demo.URIConstants.VIEW;
/**
*
*/
@API(level = AbstractURLAliasProvider.CURRENT_LEVEL)
public class ReqDemoUrlProvider extends AbstractURLAliasProvider {
@Override
public URLAlias[] registerAlias() {
return new URLAlias[]{
URLAliasFactory.createPluginAlias(CREATE, CREATE, true),
URLAliasFactory.createPluginAlias(VIEW, VIEW, true),
URLAliasFactory.createPluginAlias(SEARCH, SEARCH, true),
};
}
@Override
public int currentAPILevel() {
return CURRENT_LEVEL;
}
@Override
public String mark4Provider() {
return getClass().getName();
}
}
Loading…
Cancel
Save