LAPTOP-SB56SG4Q\86185
3 years ago
16 changed files with 752 additions and 1 deletions
@ -1,3 +1,6 @@ |
|||||||
# demo-template-encrypt |
# demo-template-encrypt |
||||||
|
|
||||||
模板综合加解密专题示例 |
模板综合加解密专题示例\ |
||||||
|
demo生效后,可以在设计器的 模板 工具栏中 增加一个模板密钥的菜单项\ |
||||||
|
选择后,可以为当前正在编辑的模板设置一个加密密钥。\ |
||||||
|
设置密钥的模板会被密钥加密,以后编辑时都需要先输入并验证密钥的正确后才能正常编辑 |
@ -0,0 +1,125 @@ |
|||||||
|
|
||||||
|
apply plugin: 'java' |
||||||
|
|
||||||
|
[compileJava,compileTestJava]*.options*.encoding = 'UTF-8' |
||||||
|
|
||||||
|
ext { |
||||||
|
/** |
||||||
|
* 项目中依赖的jar的路径 |
||||||
|
* 1.如果依赖的jar需要打包到zip中,放置在lib根目录下 |
||||||
|
* 2.如果依赖的jar仅仅是编译时需要,防止在lib下子目录下即可 |
||||||
|
*/ |
||||||
|
libPath = "$projectDir/../../webroot/WEB-INF/lib" |
||||||
|
|
||||||
|
/** |
||||||
|
* 是否对插件的class进行加密保护,防止反编译 |
||||||
|
*/ |
||||||
|
guard = true |
||||||
|
|
||||||
|
def pluginInfo = getPluginInfo() |
||||||
|
pluginPre = "fine-plugin" |
||||||
|
pluginName = pluginInfo.id |
||||||
|
pluginVersion = pluginInfo.version |
||||||
|
|
||||||
|
outputPath = "$projectDir/../../webroot/WEB-INF/plugins/plugin-" + pluginName + "-1.0/classes" |
||||||
|
} |
||||||
|
|
||||||
|
group = 'com.fr.plugin' |
||||||
|
version = '10.0' |
||||||
|
sourceCompatibility = '8' |
||||||
|
|
||||||
|
sourceSets { |
||||||
|
main { |
||||||
|
java.outputDir = file(outputPath) |
||||||
|
output.resourcesDir = file(outputPath) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
ant.importBuild("encrypt.xml") |
||||||
|
//定义ant变量 |
||||||
|
ant.projectDir = projectDir |
||||||
|
ant.references["compile.classpath"] = ant.path { |
||||||
|
fileset(dir: libPath, includes: '**/*.jar') |
||||||
|
fileset(dir: ".",includes:"**/*.jar" ) |
||||||
|
} |
||||||
|
|
||||||
|
classes.dependsOn('clean') |
||||||
|
|
||||||
|
task copyFiles(type: Copy,dependsOn: 'classes'){ |
||||||
|
from outputPath |
||||||
|
into "$projectDir/classes" |
||||||
|
} |
||||||
|
|
||||||
|
task preJar(type:Copy,dependsOn: guard ? 'compile_encrypt_javas' : 'compile_plain_javas'){ |
||||||
|
from "$projectDir/classes" |
||||||
|
into "$projectDir/transform-classes" |
||||||
|
include "**/*.*" |
||||||
|
} |
||||||
|
jar.dependsOn("preJar") |
||||||
|
|
||||||
|
task makeJar(type: Jar,dependsOn: preJar){ |
||||||
|
from fileTree(dir: "$projectDir/transform-classes") |
||||||
|
baseName pluginPre |
||||||
|
appendix pluginName |
||||||
|
version pluginVersion |
||||||
|
destinationDir = file("$buildDir/libs") |
||||||
|
|
||||||
|
doLast(){ |
||||||
|
delete file("$projectDir/classes") |
||||||
|
delete file("$projectDir/transform-classes") |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
task copyFile(type: Copy,dependsOn: ["makeJar"]){ |
||||||
|
from "$buildDir/libs" |
||||||
|
from("$projectDir/lib") { |
||||||
|
include "*.jar" |
||||||
|
} |
||||||
|
from "$projectDir/plugin.xml" |
||||||
|
into file("$buildDir/temp/plugin") |
||||||
|
} |
||||||
|
|
||||||
|
task zip(type:Zip,dependsOn:["copyFile"]){ |
||||||
|
from "$buildDir/temp/plugin" |
||||||
|
destinationDir file("$buildDir/install") |
||||||
|
baseName pluginPre |
||||||
|
appendix pluginName |
||||||
|
version pluginVersion |
||||||
|
} |
||||||
|
|
||||||
|
//控制build时包含哪些文件,排除哪些文件 |
||||||
|
processResources { |
||||||
|
// exclude everything |
||||||
|
// 用*.css没效果 |
||||||
|
// exclude '**/*.css' |
||||||
|
// except this file |
||||||
|
// include 'xx.xml' |
||||||
|
} |
||||||
|
|
||||||
|
/*读取plugin.xml中的version*/ |
||||||
|
def getPluginInfo(){ |
||||||
|
def xmlFile = file("plugin.xml") |
||||||
|
if (!xmlFile.exists()) { |
||||||
|
return ["id":"none", "version":"1.0.0"] |
||||||
|
} |
||||||
|
def plugin = new XmlParser().parse(xmlFile) |
||||||
|
def version = plugin.version[0].text() |
||||||
|
def id = plugin.id[0].text() |
||||||
|
return ["id":id,"version":version] |
||||||
|
} |
||||||
|
|
||||||
|
repositories { |
||||||
|
mavenLocal() |
||||||
|
maven { |
||||||
|
url = uri('http://mvn.finedevelop.com/repository/maven-public/') |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
dependencies { |
||||||
|
//implementation project(":tools:tool-dynamic-agent") |
||||||
|
//使用本地jar |
||||||
|
implementation fileTree(dir: 'lib', include: ['**/*.jar']) |
||||||
|
implementation fileTree(dir: libPath, include: ['**/*.jar']) |
||||||
|
} |
||||||
|
|
||||||
|
|
@ -0,0 +1,13 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
||||||
|
<project> |
||||||
|
<target name="compile_encrypt_javas" depends="copyFiles"> |
||||||
|
<echo message="加密文件"/> |
||||||
|
<echo message="${projectDir}"/> |
||||||
|
<taskdef name="pretreatment" classname="com.fr.plugin.pack.PluginPretreatmentTask"> |
||||||
|
<classpath refid="compile.classpath"/> |
||||||
|
</taskdef> |
||||||
|
<pretreatment baseDir="${projectDir}"/> |
||||||
|
</target> |
||||||
|
<target name="compile_plain_javas" depends="copyFiles"> |
||||||
|
</target> |
||||||
|
</project> |
Binary file not shown.
@ -0,0 +1,23 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?><plugin> |
||||||
|
<id>com.tptj.demo.hg.template.encrypt.v10</id> |
||||||
|
<name><![CDATA[ template encrypt ]]></name> |
||||||
|
<active>yes</active> |
||||||
|
<version>1.0</version> |
||||||
|
<env-version>10.0</env-version> |
||||||
|
<vendor>tptj</vendor> |
||||||
|
<jartime>2019-07-18</jartime> |
||||||
|
<description><![CDATA[ ]]></description> |
||||||
|
<change-notes><![CDATA[]]></change-notes> |
||||||
|
<main-package>com.tptj.demo.hg.template.encrypt</main-package> |
||||||
|
<function-recorder class="com.tptj.demo.hg.template.encrypt.LifeCycle"/> |
||||||
|
<lifecycle-monitor class="com.tptj.demo.hg.template.encrypt.LifeCycle"/> |
||||||
|
<extra-core> |
||||||
|
<IOFileAttrMark class="com.tptj.demo.hg.template.encrypt.ui.SpEncryptAttrMark"/> |
||||||
|
</extra-core> |
||||||
|
<extra-designer> |
||||||
|
<MenuHandler class="com.tptj.demo.hg.template.encrypt.ui.MenuEncryptor"/> |
||||||
|
</extra-designer> |
||||||
|
<extra-report> |
||||||
|
<TemplateEncryptProvider class="com.tptj.demo.hg.template.encrypt.DemoEncryptor"/> |
||||||
|
</extra-report> |
||||||
|
</plugin> |
@ -0,0 +1,28 @@ |
|||||||
|
package com.fr.design.mainframe.app; |
||||||
|
|
||||||
|
import com.fr.file.FILE; |
||||||
|
import com.fr.main.impl.WorkBook; |
||||||
|
import com.tptj.demo.hg.template.encrypt.BaseInterceptor; |
||||||
|
import com.tptj.tool.hg.dynamic.agent.source.AccessPoint; |
||||||
|
import com.tptj.tool.hg.dynamic.agent.source.Context; |
||||||
|
import com.tptj.tool.hg.dynamic.agent.source.Source; |
||||||
|
import com.tptj.tool.hg.dynamic.agent.version.ModuleReport; |
||||||
|
import com.tptj.tool.hg.dynamic.agent.version.VersionChecker; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* @author 秃破天际 |
||||||
|
* @version 10.0 |
||||||
|
* Created by 秃破天际 on 2021/9/11 |
||||||
|
**/ |
||||||
|
@VersionChecker(value = 10020210101l, loader = ModuleReport.class) |
||||||
|
@Source(CptApp.class) |
||||||
|
public class SpCptApp extends Context { |
||||||
|
|
||||||
|
@AccessPoint |
||||||
|
public WorkBook asIOFile(FILE file, boolean needCheck) { |
||||||
|
BaseInterceptor.intercept4Edit(file); |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,29 @@ |
|||||||
|
package com.fr.design.mainframe.app; |
||||||
|
|
||||||
|
import com.fr.base.io.EncryptIOFileProxy; |
||||||
|
import com.tptj.demo.hg.template.encrypt.BaseInterceptor; |
||||||
|
import com.tptj.tool.hg.dynamic.agent.source.AccessPoint; |
||||||
|
import com.tptj.tool.hg.dynamic.agent.source.Context; |
||||||
|
import com.tptj.tool.hg.dynamic.agent.source.Source; |
||||||
|
import com.tptj.tool.hg.dynamic.agent.version.ModuleReport; |
||||||
|
import com.tptj.tool.hg.dynamic.agent.version.VersionChecker; |
||||||
|
|
||||||
|
import java.io.OutputStream; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author 秃破天际 |
||||||
|
* @version 10.0 |
||||||
|
* Created by 秃破天际 on 2021/9/11 |
||||||
|
* 注入EncryptIOFileProxy#export的切面,在保存模板时,传递密钥信息,以便加密 |
||||||
|
**/ |
||||||
|
@VersionChecker(value = 10020210101l, loader = ModuleReport.class) |
||||||
|
@Source(EncryptIOFileProxy.class) |
||||||
|
public class SpEncryptIOFileProxy extends Context { |
||||||
|
|
||||||
|
@AccessPoint |
||||||
|
public boolean export(OutputStream out) throws Exception { |
||||||
|
BaseInterceptor.intercept4Save(getOrigin()); |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,28 @@ |
|||||||
|
package com.fr.design.mainframe.app; |
||||||
|
|
||||||
|
import com.fr.file.FILE; |
||||||
|
import com.fr.form.main.Form; |
||||||
|
import com.tptj.demo.hg.template.encrypt.BaseInterceptor; |
||||||
|
import com.tptj.tool.hg.dynamic.agent.source.AccessPoint; |
||||||
|
import com.tptj.tool.hg.dynamic.agent.source.Context; |
||||||
|
import com.tptj.tool.hg.dynamic.agent.source.Source; |
||||||
|
import com.tptj.tool.hg.dynamic.agent.version.ModuleReport; |
||||||
|
import com.tptj.tool.hg.dynamic.agent.version.VersionChecker; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author 秃破天际 |
||||||
|
* @version 10.0 |
||||||
|
* Created by 秃破天际 on 2021/9/12 |
||||||
|
* 注入FormApp#asIOFile 的切面,在打开加密form时,注入密码输入UI交互 |
||||||
|
**/ |
||||||
|
@VersionChecker(value = 10020210101l, loader = ModuleReport.class) |
||||||
|
@Source(FormApp.class) |
||||||
|
public class SpFormApp extends Context { |
||||||
|
|
||||||
|
@AccessPoint |
||||||
|
public Form asIOFile(FILE file) { |
||||||
|
BaseInterceptor.intercept4Edit(file); |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,46 @@ |
|||||||
|
package com.tptj.demo.hg.template.encrypt; |
||||||
|
|
||||||
|
import com.fr.base.io.EncryptIOFileProxy; |
||||||
|
import com.fr.base.io.IOFile; |
||||||
|
import com.fr.file.FILE; |
||||||
|
import com.fr.invoke.Reflect; |
||||||
|
import com.fr.log.FineLoggerFactory; |
||||||
|
import com.tptj.demo.hg.template.encrypt.ui.DecodeDialog; |
||||||
|
import com.tptj.demo.hg.template.encrypt.ui.SpEncryptAttrMark; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author 秃破天际 |
||||||
|
* @version 10.0 |
||||||
|
* Created by 秃破天际 on 2021/9/12 |
||||||
|
**/ |
||||||
|
public class BaseInterceptor { |
||||||
|
/** |
||||||
|
* 在打开模板前对加密的模板插入输入密码的弹窗 |
||||||
|
* @param file |
||||||
|
*/ |
||||||
|
public static void intercept4Edit(FILE file){ |
||||||
|
try { |
||||||
|
file.asInputStream(); |
||||||
|
if( !DemoEncryptor.hasSecret() ){ |
||||||
|
return; |
||||||
|
} |
||||||
|
String secret = DemoEncryptor.getSecret(); |
||||||
|
secret = new DecodeDialog(file,secret).getSecret(); |
||||||
|
DemoEncryptor.setSecret(secret); |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error(e,e.getMessage()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 在保存模板前获取配置的模板密钥,以便加密接口进行加密 |
||||||
|
* @param origin |
||||||
|
*/ |
||||||
|
public static void intercept4Save( EncryptIOFileProxy origin ){ |
||||||
|
IOFile report = Reflect.on(origin).get("file"); |
||||||
|
SpEncryptAttrMark mark = report.getAttrMark(SpEncryptAttrMark.XML_TAG); |
||||||
|
if( null != mark ){ |
||||||
|
DemoEncryptor.setSecret(mark.getSecret()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,117 @@ |
|||||||
|
package com.tptj.demo.hg.template.encrypt; |
||||||
|
|
||||||
|
import com.fr.general.CommonIOUtils; |
||||||
|
import com.fr.report.fun.impl.AbstractTemplateEncryptProvider; |
||||||
|
import com.fr.security.SecurityToolbox; |
||||||
|
import com.fr.stable.CodeUtils; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream; |
||||||
|
import java.io.InputStream; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author 秃破天际 |
||||||
|
* @version 10.0 |
||||||
|
* Created by 秃破天际 on 2021/9/12 |
||||||
|
**/ |
||||||
|
public class DemoEncryptor extends AbstractTemplateEncryptProvider { |
||||||
|
|
||||||
|
public static final String TAG_START = "-----Encrypt Start-----"; |
||||||
|
public static final String TAG_END = "-----Encrypt End-----"; |
||||||
|
|
||||||
|
public static ThreadLocal<String> holder = new ThreadLocal<String>(); |
||||||
|
public static ThreadLocal<Integer> pos = new ThreadLocal<Integer>(); |
||||||
|
public static ThreadLocal<Boolean> init = new ThreadLocal<Boolean>(); |
||||||
|
|
||||||
|
public static void setSecret(String secret) { |
||||||
|
holder.set(secret); |
||||||
|
} |
||||||
|
|
||||||
|
public static String getSecret() { |
||||||
|
return holder.get(); |
||||||
|
} |
||||||
|
|
||||||
|
public static boolean hasSecret() { |
||||||
|
return StringUtils.isNotEmpty(getSecret()); |
||||||
|
} |
||||||
|
|
||||||
|
public static int getPos(){ |
||||||
|
return pos.get(); |
||||||
|
} |
||||||
|
|
||||||
|
public static void setPos(int idx){ |
||||||
|
pos.set(idx); |
||||||
|
} |
||||||
|
|
||||||
|
public static void initData(InputStream in){ |
||||||
|
init.set(true); |
||||||
|
String data = StringUtils.EMPTY; |
||||||
|
try{ |
||||||
|
data = CommonIOUtils.inputStream2String(in); |
||||||
|
if(!data.startsWith(TAG_START)){ |
||||||
|
setSecret(StringUtils.EMPTY); |
||||||
|
setPos(-1); |
||||||
|
return; |
||||||
|
} |
||||||
|
int end = data.indexOf(TAG_END); |
||||||
|
String part = data.substring(TAG_START.length(),end); |
||||||
|
String sha = part.substring(0,64); |
||||||
|
String code = part.substring(64); |
||||||
|
String secret = CodeUtils.passwordDecode("___"+code); |
||||||
|
if( !CodeUtils.md5Encode(secret, StringUtils.EMPTY,"SHA-256").equals(sha) ){ |
||||||
|
setSecret(StringUtils.EMPTY); |
||||||
|
setPos(-1); |
||||||
|
return; |
||||||
|
} |
||||||
|
setSecret(secret); |
||||||
|
setPos(end+TAG_END.length()); |
||||||
|
}catch(Exception e){ |
||||||
|
setSecret(StringUtils.EMPTY); |
||||||
|
setPos(-1); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private String codePassword(){ |
||||||
|
String secret = getSecret(); |
||||||
|
String code = CodeUtils.passwordEncode(secret).substring(3); |
||||||
|
String sha = CodeUtils.md5Encode(secret, StringUtils.EMPTY,"SHA-256"); |
||||||
|
return sha+code; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public InputStream encode(InputStream in) { |
||||||
|
if( !hasSecret() ){ |
||||||
|
return in; |
||||||
|
} |
||||||
|
byte[] bytes = CommonIOUtils.inputStream2Bytes(in); |
||||||
|
try{ |
||||||
|
String secret = getSecret(); |
||||||
|
String data = new String(bytes,"UTF-8"); |
||||||
|
data = TAG_START +codePassword()+TAG_END+ |
||||||
|
SecurityToolbox.aesEncrypt( data, secret); |
||||||
|
return new ByteArrayInputStream(data.getBytes("UTF-8")); |
||||||
|
}catch (Exception e){ |
||||||
|
return new ByteArrayInputStream(bytes); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public InputStream decode(InputStream in) { |
||||||
|
byte[] bytes = CommonIOUtils.inputStream2Bytes(in); |
||||||
|
try{ |
||||||
|
if( !Boolean.TRUE.equals(init.get()) ){ |
||||||
|
initData(new ByteArrayInputStream(bytes)); |
||||||
|
} |
||||||
|
if( !hasSecret() ){ |
||||||
|
return new ByteArrayInputStream(bytes); |
||||||
|
} |
||||||
|
String data = new String(bytes,"UTF-8"); |
||||||
|
data = data.substring( getPos() ); |
||||||
|
data = SecurityToolbox.aesDecrypt( data, getSecret() ); |
||||||
|
return new ByteArrayInputStream(data.getBytes("UTF-8")); |
||||||
|
}catch (Exception e){ |
||||||
|
return new ByteArrayInputStream(bytes); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,35 @@ |
|||||||
|
package com.tptj.demo.hg.template.encrypt; |
||||||
|
|
||||||
|
import com.fr.design.mainframe.app.SpCptApp; |
||||||
|
import com.fr.design.mainframe.app.SpEncryptIOFileProxy; |
||||||
|
import com.fr.design.mainframe.app.SpFormApp; |
||||||
|
import com.fr.intelli.record.Focus; |
||||||
|
import com.fr.plugin.context.PluginContext; |
||||||
|
import com.fr.plugin.observer.inner.AbstractPluginLifecycleMonitor; |
||||||
|
import com.fr.record.analyzer.EnableMetrics; |
||||||
|
import com.tptj.tool.hg.dynamic.agent.base.DynamicAgent; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author 秃破天际 |
||||||
|
* @version 10.0 |
||||||
|
* Created by 秃破天际 on 2021/9/11 |
||||||
|
**/ |
||||||
|
@EnableMetrics |
||||||
|
public class LifeCycle extends AbstractPluginLifecycleMonitor { |
||||||
|
public static final String PLUGIN_ID = "com.tptj.demo.hg.template.encrypt.v10"; |
||||||
|
public static final String PLUGIN_NAME = "template encrypt"; |
||||||
|
|
||||||
|
@Override |
||||||
|
@Focus(id = PLUGIN_ID, text = PLUGIN_NAME) |
||||||
|
public void afterRun(PluginContext context) { |
||||||
|
DynamicAgent.getInstance().register( |
||||||
|
new SpEncryptIOFileProxy(), |
||||||
|
new SpCptApp(), |
||||||
|
new SpFormApp()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void beforeStop(PluginContext context) { |
||||||
|
DynamicAgent.getInstance().reset(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,88 @@ |
|||||||
|
package com.tptj.demo.hg.template.encrypt.ui; |
||||||
|
|
||||||
|
import com.fr.base.BaseUtils; |
||||||
|
import com.fr.design.gui.ibutton.UIButton; |
||||||
|
import com.fr.design.gui.ilable.UILabel; |
||||||
|
import com.fr.design.gui.itextfield.UITextField; |
||||||
|
import com.fr.design.utils.gui.GUICoreUtils; |
||||||
|
import com.fr.file.FILE; |
||||||
|
import com.fr.general.ComparatorUtils; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
|
||||||
|
import javax.swing.*; |
||||||
|
import java.awt.*; |
||||||
|
import java.awt.event.ActionEvent; |
||||||
|
import java.awt.event.ActionListener; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author 秃破天际 |
||||||
|
* @version 10.0 |
||||||
|
* Created by 秃破天际 on 2021/9/12 |
||||||
|
**/ |
||||||
|
public class DecodeDialog { |
||||||
|
private UITextField jt; |
||||||
|
private UIButton confirmButton; |
||||||
|
private UILabel hintsLabel; |
||||||
|
private JDialog jd; |
||||||
|
private FILE file; |
||||||
|
private String secret = StringUtils.EMPTY; |
||||||
|
|
||||||
|
public DecodeDialog(final FILE file, final String key) { |
||||||
|
this.file = file; |
||||||
|
|
||||||
|
jd = new JDialog(); |
||||||
|
jd.setLayout(null); |
||||||
|
UILabel newNameLable = new UILabel(Toolkit.i18nText("Fine-Design_Basic_ECP_Input_Pwd")); |
||||||
|
newNameLable.setBounds(20, 10, 130, 30); |
||||||
|
jt = new UITextField(StringUtils.EMPTY); |
||||||
|
jt.selectAll(); |
||||||
|
jt.setBounds(130, 15, 150, 20); |
||||||
|
jd.add(newNameLable); |
||||||
|
jd.add(jt); |
||||||
|
|
||||||
|
hintsLabel = new UILabel(); |
||||||
|
hintsLabel.setBounds(20, 50, 250, 30); |
||||||
|
hintsLabel.setForeground(Color.RED); |
||||||
|
hintsLabel.setVisible(false); |
||||||
|
|
||||||
|
confirmButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Confirm")); |
||||||
|
confirmButton.setBounds(180, 90, 60, 25); |
||||||
|
confirmButton.addActionListener(new ActionListener() { |
||||||
|
public void actionPerformed(ActionEvent e) { |
||||||
|
secret = jt.getText(); |
||||||
|
if(ComparatorUtils.equals(secret, key)){ |
||||||
|
jd.dispose(); |
||||||
|
}else{ |
||||||
|
hintsLabel.setText(Toolkit.i18nText("Fine-Design_Basic_ECP_Re_Input")); |
||||||
|
hintsLabel.setVisible(true); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
UIButton cancelButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Cancel")); |
||||||
|
cancelButton.setBounds(250, 90, 60, 25); |
||||||
|
cancelButton.addActionListener(new ActionListener() { |
||||||
|
public void actionPerformed(ActionEvent e) { |
||||||
|
jd.dispose(); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
jd.add(cancelButton); |
||||||
|
jd.add(confirmButton); |
||||||
|
jd.add(hintsLabel); |
||||||
|
jd.setSize(340, 180); |
||||||
|
jd.setModal(true); |
||||||
|
jd.setTitle(Toolkit.i18nText("Fine-Design_Basic_ECP_Decode")); |
||||||
|
jd.setResizable(false); |
||||||
|
jd.setAlwaysOnTop(true); |
||||||
|
jd.setIconImage(BaseUtils.readImage("/com/fr/base/images/oem/logo.png")); |
||||||
|
jd.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); |
||||||
|
GUICoreUtils.centerWindow(jd); |
||||||
|
jd.setVisible(true); |
||||||
|
} |
||||||
|
|
||||||
|
public String getSecret() { |
||||||
|
return secret; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,54 @@ |
|||||||
|
package com.tptj.demo.hg.template.encrypt.ui; |
||||||
|
|
||||||
|
import com.fr.base.io.AttrMark; |
||||||
|
import com.fr.base.svg.IconUtils; |
||||||
|
import com.fr.design.actions.JTemplateAction; |
||||||
|
import com.fr.design.dialog.DialogActionAdapter; |
||||||
|
import com.fr.design.dialog.UIDialog; |
||||||
|
import com.fr.design.mainframe.DesignerContext; |
||||||
|
import com.fr.design.mainframe.JTemplate; |
||||||
|
import com.fr.report.fit.FitProvider; |
||||||
|
|
||||||
|
import java.awt.*; |
||||||
|
import java.awt.event.ActionEvent; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author 秃破天际 |
||||||
|
* @version 10.0 |
||||||
|
* Created by 秃破天际 on 2021/9/12 |
||||||
|
**/ |
||||||
|
public class MenuEncryptAction extends JTemplateAction { |
||||||
|
private static final Dimension MEDIUM = new Dimension(300, 120); |
||||||
|
public MenuEncryptAction(JTemplate template) { |
||||||
|
super(template); |
||||||
|
setName("模板加密"); |
||||||
|
setSmallIcon(IconUtils.readIcon("com/fr/design/images/buttonicon/icon_lock_enabled.png")); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void actionPerformed(ActionEvent e) { |
||||||
|
JTemplate jwb = getEditingComponent(); |
||||||
|
if ( null == jwb ) { |
||||||
|
return; |
||||||
|
} |
||||||
|
//当前的模板
|
||||||
|
FitProvider wbTpl = (FitProvider) jwb.getTarget(); |
||||||
|
if( jwb.isJWorkBook() ){ |
||||||
|
//如果是cpt
|
||||||
|
}else{ |
||||||
|
//不是cpt
|
||||||
|
} |
||||||
|
SecretPane pane = new SecretPane( (AttrMark) wbTpl ); |
||||||
|
UIDialog dialog = pane.showUnsizedWindow(DesignerContext.getDesignerFrame(), new DialogActionAdapter() { |
||||||
|
@Override |
||||||
|
public void doOk() { |
||||||
|
//做某些操作 从 pane中读取相关的交互结果设置到当前的模板中一般是这样
|
||||||
|
pane.update(); |
||||||
|
jwb.fireTargetModified(); |
||||||
|
} |
||||||
|
}); |
||||||
|
pane.populate(); |
||||||
|
dialog.setSize(MEDIUM); |
||||||
|
dialog.setVisible(true); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,49 @@ |
|||||||
|
package com.tptj.demo.hg.template.encrypt.ui; |
||||||
|
|
||||||
|
import com.fr.design.fun.impl.AbstractMenuHandler; |
||||||
|
import com.fr.design.mainframe.DesignerContext; |
||||||
|
import com.fr.design.mainframe.JTemplate; |
||||||
|
import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus; |
||||||
|
import com.fr.design.menu.ShortCut; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author 秃破天际 |
||||||
|
* @version 10.0 |
||||||
|
* Created by 秃破天际 on 2021/9/12 |
||||||
|
**/ |
||||||
|
public class MenuEncryptor extends AbstractMenuHandler { |
||||||
|
private static final int INSERT_POSITION = 2; |
||||||
|
@Override |
||||||
|
public int insertPosition(int i) { |
||||||
|
return INSERT_POSITION; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean insertSeparatorBefore() { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean insertSeparatorAfter() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String category() { |
||||||
|
return TEMPLATE; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public ShortCut shortcut(){ |
||||||
|
JTemplate template = DesignerContext.getDesignerFrame().getSelectedJTemplate(); |
||||||
|
return shortcut(template); |
||||||
|
} |
||||||
|
@Override |
||||||
|
public ShortCut shortcut(ToolBarMenuDockPlus plus) { |
||||||
|
//往ToolBarMenuDockPlus里塞感觉也很糟.
|
||||||
|
if (!(plus instanceof JTemplate)){ |
||||||
|
return null; |
||||||
|
} |
||||||
|
return new MenuEncryptAction( (JTemplate)plus ); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,54 @@ |
|||||||
|
package com.tptj.demo.hg.template.encrypt.ui; |
||||||
|
|
||||||
|
import com.fr.base.io.AttrMark; |
||||||
|
import com.fr.design.dialog.BasicPane; |
||||||
|
import com.fr.design.gui.ilable.UILabel; |
||||||
|
import com.fr.design.gui.itextfield.UITextField; |
||||||
|
import com.fr.design.layout.FRGUIPaneFactory; |
||||||
|
import com.fr.design.layout.TableLayout; |
||||||
|
import com.fr.design.layout.TableLayoutHelper; |
||||||
|
|
||||||
|
import javax.swing.*; |
||||||
|
import java.awt.*; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author 秃破天际 |
||||||
|
* @version 10.0 |
||||||
|
* Created by 秃破天际 on 2021/9/12 |
||||||
|
**/ |
||||||
|
public class SecretPane extends BasicPane { |
||||||
|
|
||||||
|
private UITextField w_secret; |
||||||
|
private AttrMark container; |
||||||
|
public SecretPane( AttrMark container ){ |
||||||
|
this.container = container; |
||||||
|
w_secret = new UITextField(); |
||||||
|
setLayout(FRGUIPaneFactory.createM_BorderLayout()); |
||||||
|
JPanel pane = TableLayoutHelper.createTableLayoutPane( |
||||||
|
new Component[][]{ |
||||||
|
{new UILabel("加密密钥:"), w_secret} |
||||||
|
}, |
||||||
|
new double[]{TableLayout.PREFERRED}, |
||||||
|
new double[]{ TableLayout.PREFERRED,TableLayout.FILL} |
||||||
|
); |
||||||
|
add( pane, BorderLayout.NORTH ); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String title4PopupWindow() { |
||||||
|
return "设置模板密钥"; |
||||||
|
} |
||||||
|
|
||||||
|
public void populate(){ |
||||||
|
SpEncryptAttrMark attr = container.getAttrMark(SpEncryptAttrMark.XML_TAG); |
||||||
|
if( null != attr ){ |
||||||
|
w_secret.setText( attr.getSecret() ); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void update(){ |
||||||
|
SpEncryptAttrMark attr = new SpEncryptAttrMark(); |
||||||
|
attr.setSecret( w_secret.getText() ); |
||||||
|
container.addAttrMark( attr ); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,59 @@ |
|||||||
|
package com.tptj.demo.hg.template.encrypt.ui; |
||||||
|
|
||||||
|
import com.fr.json.JSONException; |
||||||
|
import com.fr.json.JSONObject; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
import com.fr.stable.fun.impl.AbstractIOFileAttrMark; |
||||||
|
import com.fr.stable.xml.XMLPrintWriter; |
||||||
|
import com.fr.stable.xml.XMLableReader; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author 秃破天际 |
||||||
|
* @version 10.0 |
||||||
|
* Created by 秃破天际 on 2021/9/12 |
||||||
|
**/ |
||||||
|
public class SpEncryptAttrMark extends AbstractIOFileAttrMark { |
||||||
|
public final static String XML_TAG = "SpEncryptAttrMark"; |
||||||
|
|
||||||
|
private String secret; |
||||||
|
|
||||||
|
public String getSecret() { |
||||||
|
return secret; |
||||||
|
} |
||||||
|
|
||||||
|
public void setSecret(String secret) { |
||||||
|
this.secret = secret; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String xmlTag() { |
||||||
|
return XML_TAG; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void readXML(XMLableReader reader) { |
||||||
|
String tag = reader.getTagName(); |
||||||
|
if( XML_TAG.equals(tag) ){ |
||||||
|
secret = reader.getAttrAsString("secret", StringUtils.EMPTY); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void writeXML(XMLPrintWriter writer) { |
||||||
|
writer.startTAG(XML_TAG).attr("secret",secret).end(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public SpEncryptAttrMark clone() { |
||||||
|
SpEncryptAttrMark obj = (SpEncryptAttrMark)super.clone(); |
||||||
|
obj.secret = secret; |
||||||
|
return obj; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public JSONObject createJSONConfig() throws JSONException { |
||||||
|
JSONObject json = super.createJSONConfig(); |
||||||
|
json.put("secret",secret); |
||||||
|
return json; |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue