Browse Source

Pull request #491: 无jira任务, 解决 release/10.0 合 feature/10.0 冲突

Merge in CORE/base-third from ~HUGH.C/base-third:feature/10.0 to feature/10.0

* commit '6990e331db3f404af8ae381e675c9eec12dfb922': (50 commits)
  无jira任务,persist合final
  REPORT-34320 块标签前的块标签含文本且文本尾部不是空格时会多出空白行
  REPORT-33863 html图片变成了图片后文字的背景图;html图片宽度大于实际盒子宽度时,图片后的文字丢失
  REPORT-32796 h1-h6标签,默认字体加粗不生效,默认margin值不生效
  REPORT-32986 html大写标签不生效
  REPORT-33908 HTML高度计算异常(br标签中的line-height属性应该生效)
  REPORT-33908 HTML高度计算异常(br、hr 标签中的line-height属性不应该生效)
  REPORT-33819? a标签设置text-decoration,前台没有下划线但是导出有
  REPORT-33780 font-weight等属性与<b>等标签之间的优先级存在问题
  REPORT-33691 tr\td\th设置单元格对齐方式,预览生效,导出不生效
  REPORT-33029 无插件PDF导出-HTML解析:块元素(如:div、p)支持align、text-align属性
  无jira任务,编译失败
  REPORT-33491 无插件PDF导出-HTML解析:支持<th>标签加粗样式
  KERNEL-4410 集群定时任务,支持切换执行节点
  无 jira 任务, bugfix -> release 解决冲突, 更新目录结构。
  REPORT-33025 加点注解
  REPORT-33025 无插件PDF导出-HTML解析:支持<a>标签超链
  REPORT-32592 html 以<a>、<br> or <hr> 标签开头时,丢失line-height属性
  REPORT-33028 review 改进
  REPORT-33028 无插件PDF导出-HTML解析:块元素支持margin、padding 属性
  ...
research/11.0
Hugh.C 4 years ago
parent
commit
e533acbf09
  1. 53
      build.third_step0.gradle
  2. 9
      fine-itext-old/src/main/java/com/fr/third/com/lowagie/text/html/simpleparser/HTMLWorker.java
  3. 1
      fine-itext-old/src/main/java/com/fr/third/com/lowagie/text/pdf/PdfGraphics2D.java
  4. 37
      fine-itext-old/src/main/java/com/fr/third/com/lowagie/text/xml/simpleparser/SimpleXMLParser.java
  5. 23
      fine-itext/src/main/java/com/fr/third/v2/lowagie/text/html/Markup.java
  6. 31
      fine-itext/src/main/java/com/fr/third/v2/lowagie/text/html/simpleparser/ChainedProperties.java
  7. 113
      fine-itext/src/main/java/com/fr/third/v2/lowagie/text/html/simpleparser/FactoryProperties.java
  8. 19
      fine-itext/src/main/java/com/fr/third/v2/lowagie/text/html/simpleparser/HTMLWorker.java
  9. 12
      fine-itext/src/main/java/com/fr/third/v2/lowagie/text/html/simpleparser/HtmlConstants.java
  10. 5
      fine-itext/src/main/java/com/fr/third/v2/lowagie/text/html/simpleparser/IncCell.java
  11. 90
      fine-itext/src/main/java/com/fr/third/v2/lowagie/text/html/utils/DefaultPropertiesHandleUtils.java
  12. 27
      fine-itext/src/main/java/com/fr/third/v2/lowagie/text/pdf/PdfChunk.java
  13. 1
      fine-itext/src/main/java/com/fr/third/v2/lowagie/text/pdf/PdfLine.java
  14. 2
      fine-itext/src/main/java/com/fr/third/v2/lowagie/text/xml/simpleparser/SimpleXMLParser.java
  15. 2
      fine-jackson/src/main/java/com/fr/third/fasterxml/jackson/databind/type/ClassFactory.java
  16. 3
      fine-jackson/src/main/java/com/fr/third/fasterxml/jackson/databind/type/TypeFactory.java
  17. 7
      fine-quartz/src/main/java/com/fr/third/v2/org/quartz/Scheduler.java
  18. 4
      fine-quartz/src/main/java/com/fr/third/v2/org/quartz/Trigger.java
  19. 9
      fine-quartz/src/main/java/com/fr/third/v2/org/quartz/TriggerBuilder.java
  20. 4
      fine-quartz/src/main/java/com/fr/third/v2/org/quartz/core/QuartzScheduler.java
  21. 5
      fine-quartz/src/main/java/com/fr/third/v2/org/quartz/impl/RemoteMBeanScheduler.java
  22. 5
      fine-quartz/src/main/java/com/fr/third/v2/org/quartz/impl/RemoteScheduler.java
  23. 5
      fine-quartz/src/main/java/com/fr/third/v2/org/quartz/impl/StdScheduler.java
  24. 5
      fine-quartz/src/main/java/com/fr/third/v2/org/quartz/impl/StdSchedulerFactory.java
  25. 2
      fine-quartz/src/main/java/com/fr/third/v2/org/quartz/impl/jdbcjobstore/Constants.java
  26. 6
      fine-quartz/src/main/java/com/fr/third/v2/org/quartz/impl/jdbcjobstore/DriverDelegate.java
  27. 56
      fine-quartz/src/main/java/com/fr/third/v2/org/quartz/impl/jdbcjobstore/JobStoreSupport.java
  28. 1
      fine-quartz/src/main/java/com/fr/third/v2/org/quartz/impl/jdbcjobstore/PointbaseDelegate.java
  29. 58
      fine-quartz/src/main/java/com/fr/third/v2/org/quartz/impl/jdbcjobstore/StdJDBCConstants.java
  30. 70
      fine-quartz/src/main/java/com/fr/third/v2/org/quartz/impl/jdbcjobstore/StdJDBCDelegate.java
  31. 1
      fine-quartz/src/main/java/com/fr/third/v2/org/quartz/impl/jdbcjobstore/oracle/OracleDelegate.java
  32. 33
      fine-quartz/src/main/java/com/fr/third/v2/org/quartz/impl/triggers/AbstractTrigger.java
  33. 10
      fine-quartz/src/main/java/com/fr/third/v2/org/quartz/simpl/RAMJobStore.java
  34. 13
      fine-quartz/src/main/java/com/fr/third/v2/org/quartz/spi/JobStore.java
  35. 2
      fine-spring/pom.xml
  36. 23
      pom.xml

53
build.third_step0.gradle

@ -16,7 +16,7 @@ targetCompatibility=1.7
//lib下的jar到classes文件夹 //lib下的jar到classes文件夹
version='10.0'
jar{ jar{
baseName="fine-third" baseName="fine-third"
zip64 true zip64 true
@ -42,11 +42,21 @@ FileTree files =fileTree(dir:'./',include:'build*.gradle')
def buildDir=files[0].path.substring(0,files[0].path.lastIndexOf (java.io.File.separator)) def buildDir=files[0].path.substring(0,files[0].path.lastIndexOf (java.io.File.separator))
def branchName=buildDir.substring(buildDir.lastIndexOf (java.io.File.separator)+1) def branchName=buildDir.substring(buildDir.lastIndexOf (java.io.File.separator)+1)
def date = new Date()
def formattedDate = date.format('yyyy.MM.dd')
def srcDir="." def srcDir="."
def MVN_BRANCH = branchVariable.toUpperCase() def maven_version_build = ""
def indexV = branchName.indexOf( "%2F");
if(indexV != -1){
version= branchName.substring(indexV+3, branchName.length()).toUpperCase()
maven_version_build = project.version +"-" + branchName.substring(0, indexV).toUpperCase() +"-SNAPSHOT"
} else {
version= branchName
maven_version_build = project.version +"-SNAPSHOT"
}
// @branch - def maven_version="${version}.${formattedDate}"
def maven_version="${version}-${MVN_BRANCH}-SNAPSHOT"
def jar_version = version def jar_version = version
configurations { configurations {
@ -67,13 +77,32 @@ publishing {
groupId "com.fr.third" groupId "com.fr.third"
artifactId "fine-third" artifactId "fine-third"
version maven_version version maven_version
ext.repo = 'release'
from components.java
}
third_build(MavenPublication) {
groupId "com.fr.third"
artifactId "fine-third"
version maven_version_build
ext.repo = 'snapshot'
from components.java from components.java
} }
} }
repositories { repositories {
maven { maven {
name "release"
url "http://mvn.finedevelop.com/repository/fanruan/" url "http://mvn.finedevelop.com/repository/fanruan-release/"
credentials {
username = findProperty("NEXUS_USERNAME")
password = findProperty("NEXUS_PASSWORD")
}
}
maven {
name "snapshot"
url "http://mvn.finedevelop.com/repository/fanruan/"
credentials { credentials {
username = findProperty("NEXUS_USERNAME") username = findProperty("NEXUS_USERNAME")
password = findProperty("NEXUS_PASSWORD") password = findProperty("NEXUS_PASSWORD")
@ -83,6 +112,17 @@ publishing {
} }
} }
afterEvaluate {
tasks.withType(PublishToMavenRepository) { task ->
if (task.publication.hasProperty('repo') && task.publication.repo != task.repository.name) {
task.enabled = false
task.group = null
}
}
}
task unpack(type:Copy) { task unpack(type:Copy) {
delete classesDir delete classesDir
destinationDir=file(classesDir) destinationDir=file(classesDir)
@ -114,4 +154,3 @@ task unpack(type:Copy) {
} }
jar.dependsOn unpack jar.dependsOn unpack

9
fine-itext-old/src/main/java/com/fr/third/com/lowagie/text/html/simpleparser/HTMLWorker.java

@ -775,11 +775,14 @@ public class HTMLWorker implements SimpleXMLDocHandler, DocListener {
+ " h1 h2 h3 h4 h5 h6 img hr"; + " h1 h2 h3 h4 h5 h6 img hr";
public static final HashMap tagsSupported = new HashMap(); public static final HashMap tagsSupported = new HashMap();
public static final HashMap tagsPrefixSupported = new HashMap();
static { static {
StringTokenizer tok = new StringTokenizer(tagsSupportedString); StringTokenizer tok = new StringTokenizer(tagsSupportedString);
while (tok.hasMoreTokens()) while (tok.hasMoreTokens()) {
tagsSupported.put(tok.nextToken(), null); String s = tok.nextToken();
tagsSupported.put(s, null);
tagsPrefixSupported.put(s.charAt(0), null);
}
} }
} }

1
fine-itext-old/src/main/java/com/fr/third/com/lowagie/text/pdf/PdfGraphics2D.java

@ -433,6 +433,7 @@ public class PdfGraphics2D extends Graphics2D {
cb.setTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE); cb.setTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE);
if (strokeWidth != 1) { if (strokeWidth != 1) {
cb.setLineWidth(strokeWidth); cb.setLineWidth(strokeWidth);
oldStroke = new BasicStroke(strokeWidth);
if(realPaint instanceof Color){ if(realPaint instanceof Color){
Color color = (Color)realPaint; Color color = (Color)realPaint;
int alpha = color.getAlpha(); int alpha = color.getAlpha();

37
fine-itext-old/src/main/java/com/fr/third/com/lowagie/text/xml/simpleparser/SimpleXMLParser.java

@ -75,6 +75,7 @@
*/ */
package com.fr.third.com.lowagie.text.xml.simpleparser; package com.fr.third.com.lowagie.text.xml.simpleparser;
import com.fr.third.com.lowagie.text.html.simpleparser.HTMLWorker;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
@ -117,7 +118,7 @@ public final class SimpleXMLParser {
private final static int ATTRIBUTE_KEY = 12; private final static int ATTRIBUTE_KEY = 12;
private final static int ATTRIBUTE_EQUAL = 13; private final static int ATTRIBUTE_EQUAL = 13;
private final static int ATTRIBUTE_VALUE = 14; private final static int ATTRIBUTE_VALUE = 14;
/** the state stack */ /** the state stack */
Stack stack; Stack stack;
/** The current character. */ /** The current character. */
@ -161,7 +162,7 @@ public final class SimpleXMLParser {
String attributekey = null; String attributekey = null;
/** the attribute value. */ /** the attribute value. */
String attributevalue = null; String attributevalue = null;
/** /**
* Creates a Simple XML parser object. * Creates a Simple XML parser object.
* Call go(BufferedReader) immediately after creation. * Call go(BufferedReader) immediately after creation.
@ -207,7 +208,7 @@ public final class SimpleXMLParser {
} }
return; return;
} }
// dealing with \n and \r // dealing with \n and \r
if (character == '\n' && eol) { if (character == '\n' && eol) {
eol = false; eol = false;
@ -225,21 +226,18 @@ public final class SimpleXMLParser {
} else { } else {
columns++; columns++;
} }
switch(state) { switch(state) {
// we are in an unknown state before there's actual content // we are in an unknown state before there's actual content
case UNKNOWN: case UNKNOWN:
if(character == '<') { if(character == '<') {
saveState(TEXT); beginnOfTag((char) reader.read(), UNKNOWN);
state = TAG_ENCOUNTERED;
} }
break; break;
// we can encounter any content // we can encounter any content
case TEXT: case TEXT:
if(character == '<') { if(character == '<') {
flush(); beginnOfTag((char) reader.read(), TEXT);
saveState(state);
state = TAG_ENCOUNTERED;
} else if(character == '&') { } else if(character == '&') {
saveState(state); saveState(state);
entity.setLength(0); entity.setLength(0);
@ -499,6 +497,27 @@ public final class SimpleXMLParser {
private void saveState(int s) { private void saveState(int s) {
stack.push(new Integer(s)); stack.push(new Integer(s));
} }
/**
* 处理标签的开头若不在支持标签范围内<符号作为文本处理<1111 (仿造浏览器的处理方式)
*/
public void beginnOfTag(char c, int type) {
previousCharacter = c;
if (c == -1) {
return;
}
if (c == '/' || HTMLWorker.tagsPrefixSupported.containsKey(Character.toLowerCase(c))) {
if (type == TEXT) {
flush();
}
saveState(TEXT);
state = TAG_ENCOUNTERED;
return;
}
text.append((char) character);
nowhite = true;
}
/** /**
* Flushes the text that is currently in the buffer. * Flushes the text that is currently in the buffer.
* The text can be ignored, added to the document * The text can be ignored, added to the document

23
fine-itext/src/main/java/com/fr/third/v2/lowagie/text/html/Markup.java

@ -52,6 +52,8 @@
package com.fr.third.v2.lowagie.text.html; package com.fr.third.v2.lowagie.text.html;
import com.fr.third.v2.lowagie.text.ElementTags;
import com.fr.third.v2.lowagie.text.html.simpleparser.ChainedProperties;
import java.awt.Color; import java.awt.Color;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -231,6 +233,9 @@ public class Markup {
/** the CSS tag for the horizontal alignment of an object */ /** the CSS tag for the horizontal alignment of an object */
public static final String CSS_KEY_TEXTALIGN = "text-align"; public static final String CSS_KEY_TEXTALIGN = "text-align";
/** the CSS tag for the horizontal alignment of an object */
public static final String CSS_KEY_ALIGN = "align";
/** the CSS tag for text decorations */ /** the CSS tag for text decorations */
public static final String CSS_KEY_TEXTDECORATION = "text-decoration"; public static final String CSS_KEY_TEXTDECORATION = "text-decoration";
@ -430,6 +435,9 @@ public class Markup {
if (string.startsWith("em")) { if (string.startsWith("em")) {
return f * actualFontSize; return f * actualFontSize;
} }
if (string.startsWith("%")) {
return f * actualFontSize / 100;
}
// one ex is the x-height of a font (x-height is usually about half the // one ex is the x-height of a font (x-height is usually about half the
// font-size) // font-size)
if (string.startsWith("ex")) { if (string.startsWith("ex")) {
@ -439,6 +447,21 @@ public class Markup {
return f; return f;
} }
/**
* 解析当前字号可能是继承来的
*
* @param cprops
* @return
*/
public static float parseDefaultFontSize(ChainedProperties cprops) {
if (null == cprops) {
return DEFAULT_FONT_SIZE;
}
String size = cprops.getProperty(ElementTags.SIZE);
return null == size ? Markup.DEFAULT_FONT_SIZE : Markup.parseLength(size,
Markup.DEFAULT_FONT_SIZE);
}
/** /**
* Converts a <CODE>Color</CODE> into a HTML representation of this <CODE> * Converts a <CODE>Color</CODE> into a HTML representation of this <CODE>
* Color</CODE>. * Color</CODE>.

31
fine-itext/src/main/java/com/fr/third/v2/lowagie/text/html/simpleparser/ChainedProperties.java

@ -76,11 +76,11 @@ public class ChainedProperties {
return null; return null;
} }
public String getLastChainProperty(String key){ public String getLastChainProperty(String key) {
if (0 == chain.size()) { if (0 == chain.size()) {
return null; return null;
} }
Object obj[] = (Object[]) chain.get(chain.size()-1); Object obj[] = (Object[]) chain.get(chain.size() - 1);
HashMap prop = (HashMap) obj[1]; HashMap prop = (HashMap) obj[1];
return (String) prop.get(key); return (String) prop.get(key);
} }
@ -217,4 +217,31 @@ public class ChainedProperties {
return null; return null;
} }
/**
* 获取当前处理的标签
*
* @return 标签名
*/
public String getLastTag() {
if (chain.size() == 0) {
return null;
}
Object obj[] = (Object[]) chain.get(chain.size() - 1);
return (String) obj[0];
}
/**
* 判断 LastChain 是否存在一对 Key - value
*
* @param key
* @param value
* @return
*/
public boolean hasKvInLastChain(String key, String value) {
String actualValue = getLastChainProperty(key);
if (null == actualValue && null == value) {
return true;
}
return null == value ? actualValue.equals(value) : value.equals(actualValue);
}
} }

113
fine-itext/src/main/java/com/fr/third/v2/lowagie/text/html/simpleparser/FactoryProperties.java

@ -50,6 +50,7 @@
package com.fr.third.v2.lowagie.text.html.simpleparser; package com.fr.third.v2.lowagie.text.html.simpleparser;
import com.fr.third.v2.lowagie.text.html.CSS;
import com.fr.third.v2.lowagie.text.html.BorderAttribute; import com.fr.third.v2.lowagie.text.html.BorderAttribute;
import com.fr.third.v2.lowagie.text.html.utils.BackgroundUtil; import com.fr.third.v2.lowagie.text.html.utils.BackgroundUtil;
import com.fr.third.v2.lowagie.text.html.utils.BorderUtils; import com.fr.third.v2.lowagie.text.html.utils.BorderUtils;
@ -57,6 +58,7 @@ import java.awt.Color;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.List;
import java.util.Properties; import java.util.Properties;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import com.fr.third.v2.lowagie.text.Chunk; import com.fr.third.v2.lowagie.text.Chunk;
@ -107,6 +109,7 @@ public class FactoryProperties {
} }
return ck; return ck;
} }
private static void setParagraphLeading(Paragraph p, String leading) { private static void setParagraphLeading(Paragraph p, String leading) {
if (leading == null) { if (leading == null) {
p.setLeading(0, 1.5f); p.setLeading(0, 1.5f);
@ -150,18 +153,10 @@ public class FactoryProperties {
if (props.hasProperty("noexist-attrid")) { if (props.hasProperty("noexist-attrid")) {
p.setAttribute("noexist-attrid", props.getProperty("noexist-attrid")); p.setAttribute("noexist-attrid", props.getProperty("noexist-attrid"));
} }
for(String margin : HtmlConstants.MARGIN){
if(props.hasPropertyInChain("div", margin)){ parseAlignAttr(p, props);
String ss = props.getPropertyFromChain("div", margin); parseMarginAttr(p, props);
p.setAttribute(margin, ss); parsePaddingAttr(p, props);
}
}
for(String padding : HtmlConstants.PADDING){
if(props.hasPropertyInChain("div", padding)){
String ss = props.getPropertyFromChain("div", padding);
p.setAttribute(padding, ss);
}
}
String lastBlockTag = props.getLastBlockTag(); String lastBlockTag = props.getLastBlockTag();
//这里解析的背景属性不能是table标签的 //这里解析的背景属性不能是table标签的
@ -179,7 +174,7 @@ public class FactoryProperties {
p.setHyphenation(getHyphenation(props)); p.setHyphenation(getHyphenation(props));
setParagraphLeading(p, props.getProperty("leading")); setParagraphLeading(p, props.getProperty("leading"));
value = props.getProperty("before"); String value = props.getProperty("before");
if (value != null) { if (value != null) {
try { try {
p.setSpacingBefore(Float.parseFloat(value)); p.setSpacingBefore(Float.parseFloat(value));
@ -202,6 +197,76 @@ public class FactoryProperties {
} }
} }
/**
* 解析align属性
*
* @param p
* @param props
*/
private static void parseAlignAttr(Paragraph p, ChainedProperties props) {
String[] keys = new String[]{Markup.CSS_KEY_ALIGN, Markup.CSS_KEY_TEXTALIGN};
for (String key : keys) {
String value = props.getPropertyFromChain("div", key);
if (null == value) {
continue;
}
if (value.equalsIgnoreCase("center"))
p.setAlignment(Element.ALIGN_CENTER);
else if (value.equalsIgnoreCase("right"))
p.setAlignment(Element.ALIGN_RIGHT);
else if (value.equalsIgnoreCase("left"))
p.setAlignment(Element.ALIGN_LEFT);
else if (value.equalsIgnoreCase("justify"))
p.setAlignment(Element.ALIGN_JUSTIFIED);
}
}
/**
* 解析margin属性
*
* @param p
* @param props
*/
private static void parseMarginAttr(Paragraph p, ChainedProperties props) {
if (props.hasPropertyInChain("div", Markup.CSS_KEY_MARGIN)) {
List<String> list = Markup.parseNESW(props.getPropertyFromChain("div", Markup.CSS_KEY_MARGIN));
if (null != list && 4 == list.size()) {
for (int i = 0; i < HtmlConstants.MARGIN.size() && i < list.size(); i++) {
p.setAttribute(HtmlConstants.MARGIN.get(i), String.valueOf(Markup.parseLength(list.get(i), Markup.parseDefaultFontSize(props))));
}
}
}
for (String margin : HtmlConstants.MARGIN) {
if (props.hasPropertyInChain("div", margin)) {
String ss = props.getPropertyFromChain("div", margin);
p.setAttribute(margin, String.valueOf(Markup.parseLength(ss, Markup.parseDefaultFontSize(props))));
}
}
}
/**
* 解析padding属性
*
* @param p
* @param props
*/
private static void parsePaddingAttr(Paragraph p, ChainedProperties props) {
if (props.hasPropertyInChain("div", Markup.CSS_KEY_PADDING)) {
List<String> list = Markup.parseNESW(props.getPropertyFromChain("div", Markup.CSS_KEY_PADDING));
if (null != list && 4 == list.size()) {
for (int i = 0; i < HtmlConstants.PADDING.size() && i < list.size(); i++) {
p.setAttribute(HtmlConstants.PADDING.get(i), list.get(i));
}
}
}
for (String padding : HtmlConstants.PADDING) {
if (props.hasPropertyInChain("div", padding)) {
String ss = props.getPropertyFromChain("div", padding);
p.setAttribute(padding, ss);
}
}
}
public static Paragraph createParagraph(ChainedProperties props) { public static Paragraph createParagraph(ChainedProperties props) {
Paragraph p = new Paragraph(); Paragraph p = new Paragraph();
createParagraph(p, props); createParagraph(p, props);
@ -392,17 +457,32 @@ public class FactoryProperties {
dealWithFontSizeOrTextIndent(h, cprops, prop, key); dealWithFontSizeOrTextIndent(h, cprops, prop, key);
} else if (key.equals(Markup.CSS_KEY_FONTSTYLE)) { } else if (key.equals(Markup.CSS_KEY_FONTSTYLE)) {
String ss = prop.getProperty(key).trim().toLowerCase(); String ss = prop.getProperty(key).trim().toLowerCase();
if (ss.equals("italic") || ss.equals("oblique")) if (ss.equals("italic") || ss.equals("oblique")) {
h.put("i", null); h.put("i", null);
} else {
h.remove("i");
}
} else if (key.equals(Markup.CSS_KEY_FONTWEIGHT)) { } else if (key.equals(Markup.CSS_KEY_FONTWEIGHT)) {
String ss = prop.getProperty(key).trim().toLowerCase(); String ss = prop.getProperty(key).trim().toLowerCase();
if (ss.equals("bold") || ss.equals("700") || ss.equals("800") if (ss.equals("bold") || ss.equals("700") || ss.equals("800")
|| ss.equals("900")) || ss.equals("900")){
h.put("b", null); h.put("b", null);
}else {
h.remove("b");
}
} else if (key.equals(Markup.CSS_KEY_TEXTDECORATION)) { } else if (key.equals(Markup.CSS_KEY_TEXTDECORATION)) {
String ss = prop.getProperty(key).trim().toLowerCase(); String ss = prop.getProperty(key).trim().toLowerCase();
if (ss.equals(Markup.CSS_VALUE_UNDERLINE)) if (ss.equals(Markup.CSS_VALUE_UNDERLINE)) {
h.remove("s");
h.put("u", null); h.put("u", null);
} else if (ss.equals(Markup.CSS_VALUE_LINETHROUGH)) {
h.remove("u");
h.put("s", null);
} else {
h.remove("u");
h.remove("s");
h.put(key, ss);
}
} else if (key.equals(Markup.CSS_KEY_COLOR)) { } else if (key.equals(Markup.CSS_KEY_COLOR)) {
Color c = Markup.decodeColor(prop.getProperty(key)); Color c = Markup.decodeColor(prop.getProperty(key));
if (c != null) { if (c != null) {
@ -484,5 +564,6 @@ public class FactoryProperties {
followTags.put("strong", "b"); followTags.put("strong", "b");
followTags.put("s", "s"); followTags.put("s", "s");
followTags.put("strike", "s"); followTags.put("strike", "s");
followTags.put("del", "s");
} }
} }

19
fine-itext/src/main/java/com/fr/third/v2/lowagie/text/html/simpleparser/HTMLWorker.java

@ -50,6 +50,7 @@
package com.fr.third.v2.lowagie.text.html.simpleparser; package com.fr.third.v2.lowagie.text.html.simpleparser;
import com.fr.third.v2.lowagie.text.html.utils.DefaultPropertiesHandleUtils;
import com.fr.third.v2.lowagie.text.pdf.PdfFont; import com.fr.third.v2.lowagie.text.pdf.PdfFont;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
@ -211,16 +212,13 @@ public class HTMLWorker implements SimpleXMLDocHandler, DocListener {
return; return;
try { try {
style.applyStyle(tag, h); style.applyStyle(tag, h);
if(tag.equals("p")){ DefaultPropertiesHandleUtils.fillDefaultProperties(tag, h);
h.put(Markup.CSS_KEY_MARGINTOP, "16px");
h.put(Markup.CSS_KEY_MARGINBOTTOM, "16px");
}
String follow = (String) FactoryProperties.followTags.get(tag); String follow = (String) FactoryProperties.followTags.get(tag);
if (follow != null) { if (follow != null) {
HashMap prop = new HashMap(); HashMap prop = new HashMap();
prop.put(follow, null); prop.put(follow, null);
FactoryProperties.insertStyle(h, this.cprops);
prop.putAll(h); prop.putAll(h);
FactoryProperties.insertStyle(prop, this.cprops);
cprops.addToChain(follow, prop); cprops.addToChain(follow, prop);
return; return;
} }
@ -228,7 +226,8 @@ public class HTMLWorker implements SimpleXMLDocHandler, DocListener {
if (tag.equals(HtmlTags.ANCHOR)) { if (tag.equals(HtmlTags.ANCHOR)) {
cprops.addToChain(tag, h); cprops.addToChain(tag, h);
if (currentParagraph == null) { if (currentParagraph == null) {
currentParagraph = new Paragraph(); currentParagraph = FactoryProperties
.createParagraph(cprops);
} }
stack.push(currentParagraph); stack.push(currentParagraph);
currentParagraph = new Paragraph(); currentParagraph = new Paragraph();
@ -236,7 +235,8 @@ public class HTMLWorker implements SimpleXMLDocHandler, DocListener {
} }
if (tag.equals(HtmlTags.NEWLINE)) { if (tag.equals(HtmlTags.NEWLINE)) {
if (currentParagraph == null) { if (currentParagraph == null) {
currentParagraph = new Paragraph(); currentParagraph = FactoryProperties
.createParagraph(cprops);
} }
currentParagraph.add(factoryProperties currentParagraph.add(factoryProperties
.createChunk("\n", cprops)); .createChunk("\n", cprops));
@ -727,7 +727,8 @@ public class HTMLWorker implements SimpleXMLDocHandler, DocListener {
currentParagraph.add(chunk); currentParagraph.add(chunk);
return; return;
} }
if (content.trim().length() == 0 && content.indexOf(' ') < 0) {
if (content.trim().length() == 0 && null == currentParagraph) {
return; return;
} }
@ -821,7 +822,7 @@ public class HTMLWorker implements SimpleXMLDocHandler, DocListener {
return true; return true;
} }
public static final String tagsSupportedString = "ol ul li a pre font span br p div body table td th tr i b u sub sup em strong s strike" public static final String tagsSupportedString = "ol ul li a pre font span br p div body table td th tr i b u sub sup em strong s strike del"
+ " h1 h2 h3 h4 h5 h6 img hr"; + " h1 h2 h3 h4 h5 h6 img hr";
public static final HashMap tagsSupported = new HashMap(); public static final HashMap tagsSupported = new HashMap();

12
fine-itext/src/main/java/com/fr/third/v2/lowagie/text/html/simpleparser/HtmlConstants.java

@ -45,15 +45,16 @@ public class HtmlConstants {
INLINE_ELEMENTS.add(HtmlTags.I); INLINE_ELEMENTS.add(HtmlTags.I);
INLINE_ELEMENTS.add(HtmlTags.U); INLINE_ELEMENTS.add(HtmlTags.U);
INLINE_ELEMENTS.add(HtmlTags.EM); INLINE_ELEMENTS.add(HtmlTags.EM);
PADDING.add(Markup.CSS_KEY_PADDINGLEFT);
PADDING.add(Markup.CSS_KEY_PADDINGRIGHT);
PADDING.add(Markup.CSS_KEY_PADDINGTOP); PADDING.add(Markup.CSS_KEY_PADDINGTOP);
PADDING.add(Markup.CSS_KEY_PADDINGRIGHT);
PADDING.add(Markup.CSS_KEY_PADDINGBOTTOM); PADDING.add(Markup.CSS_KEY_PADDINGBOTTOM);
MARGIN.add(Markup.CSS_KEY_MARGINLEFT); PADDING.add(Markup.CSS_KEY_PADDINGLEFT);
MARGIN.add(Markup.CSS_KEY_MARGINRIGHT);
MARGIN.add(Markup.CSS_KEY_MARGINTOP); MARGIN.add(Markup.CSS_KEY_MARGINTOP);
MARGIN.add(Markup.CSS_KEY_MARGINRIGHT);
MARGIN.add(Markup.CSS_KEY_MARGINBOTTOM); MARGIN.add(Markup.CSS_KEY_MARGINBOTTOM);
MARGIN.add(Markup.CSS_KEY_MARGINLEFT);
//按照上 右 下 左 的顺序排 //按照上 右 下 左 的顺序排
BORDER.add(Markup.CSS_KEY_BORDERTOP); BORDER.add(Markup.CSS_KEY_BORDERTOP);
@ -75,5 +76,6 @@ public class HtmlConstants {
BORDER_COLOR.add(Markup.CSS_KEY_BORDERCOLORRIGHT); BORDER_COLOR.add(Markup.CSS_KEY_BORDERCOLORRIGHT);
BORDER_COLOR.add(Markup.CSS_KEY_BORDERCOLORBOTTOM); BORDER_COLOR.add(Markup.CSS_KEY_BORDERCOLORBOTTOM);
BORDER_COLOR.add(Markup.CSS_KEY_BORDERCOLORLEFT); BORDER_COLOR.add(Markup.CSS_KEY_BORDERCOLORLEFT);
} }
} }

5
fine-itext/src/main/java/com/fr/third/v2/lowagie/text/html/simpleparser/IncCell.java

@ -70,12 +70,13 @@ public class IncCell implements TextElementArray {
*/ */
public IncCell(String tag, ChainedProperties props) { public IncCell(String tag, ChainedProperties props) {
cell = new PdfPCell((Phrase) null); cell = new PdfPCell((Phrase) null);
cell.setHorizontalAlignment(Element.ALIGN_UNDEFINED);
String value = props.getProperty("colspan"); String value = props.getProperty("colspan");
if (value != null) if (value != null)
cell.setColspan(Integer.parseInt(value)); cell.setColspan(Integer.parseInt(value));
value = props.getProperty("align"); value = props.getProperty("align");
if (tag.equals("th")) // if (tag.equals("th"))
cell.setHorizontalAlignment(Element.ALIGN_CENTER); // cell.setHorizontalAlignment(Element.ALIGN_CENTER);
if (value != null) { if (value != null) {
if ("center".equalsIgnoreCase(value)) if ("center".equalsIgnoreCase(value))
cell.setHorizontalAlignment(Element.ALIGN_CENTER); cell.setHorizontalAlignment(Element.ALIGN_CENTER);

90
fine-itext/src/main/java/com/fr/third/v2/lowagie/text/html/utils/DefaultPropertiesHandleUtils.java

@ -0,0 +1,90 @@
package com.fr.third.v2.lowagie.text.html.utils;
import com.fr.third.v2.lowagie.text.html.HtmlTags;
import com.fr.third.v2.lowagie.text.html.Markup;
import java.util.HashMap;
import java.util.Properties;
/**
* 处理标签默认属性值
*
* @author Hugh.C
* @version 1.0
* Created by Hugh.C on 2020/7/3
*/
public class DefaultPropertiesHandleUtils {
//h1-h6 标签默认字体大小
private static final HashMap<String, String> H_TAG_DEFAULT_FONT_SIZE = new HashMap<String, String>(6);
//h1-h6 标签默认margin-top and bottom大小
private static final HashMap<String, String> H_TAG_DEFAULT_MARGIN = new HashMap<String, String>(6);
static {
H_TAG_DEFAULT_FONT_SIZE.put("h1", "2em");
H_TAG_DEFAULT_FONT_SIZE.put("h2", "1.5em");
H_TAG_DEFAULT_FONT_SIZE.put("h3", "1.17em");
H_TAG_DEFAULT_FONT_SIZE.put("h4", "1em");
H_TAG_DEFAULT_FONT_SIZE.put("h5", "0.83em");
H_TAG_DEFAULT_FONT_SIZE.put("h6", "0.67em");
H_TAG_DEFAULT_MARGIN.put("h1", "0.67em");
H_TAG_DEFAULT_MARGIN.put("h2", "0.83em");
H_TAG_DEFAULT_MARGIN.put("h3", "1em");
H_TAG_DEFAULT_MARGIN.put("h4", "1.33em");
H_TAG_DEFAULT_MARGIN.put("h5", "1.67em");
H_TAG_DEFAULT_MARGIN.put("h6", "2.33em");
}
/**
* 填充默认属性值
*
* @param tag
* @param h
*/
public static void fillDefaultProperties(String tag, HashMap h) {
if (null == tag || null == h) {
return;
}
if (HtmlTags.HEADERCELL.endsWith(tag)) {
h.put("b", null);
return;
}
if (HtmlTags.ANCHOR.equals(tag)) {
h.put("u", null);
h.put("color", "blue");
return;
}
String style = (String) h.get("style");
if (HtmlTags.PARAGRAPH.equals(tag)) {
Properties props = Markup.parseAttributes(style);
if (!props.containsKey(Markup.CSS_KEY_MARGINTOP)) {
h.put(Markup.CSS_KEY_MARGINTOP, "1em");
}
if (!props.containsKey(Markup.CSS_KEY_MARGINBOTTOM)) {
h.put(Markup.CSS_KEY_MARGINBOTTOM, "1em");
}
return;
}
if (H_TAG_DEFAULT_FONT_SIZE.containsKey(tag)) {
h.put("b", null);
Properties props = Markup.parseAttributes(style);
if (!props.containsKey(Markup.CSS_KEY_MARGINTOP)) {
h.put(Markup.CSS_KEY_MARGINTOP, H_TAG_DEFAULT_MARGIN.get(tag));
}
if (!props.containsKey(Markup.CSS_KEY_MARGINBOTTOM)) {
h.put(Markup.CSS_KEY_MARGINBOTTOM, H_TAG_DEFAULT_MARGIN.get(tag));
}
if (!props.containsKey(Markup.CSS_KEY_FONTSIZE)) {
h.put("style", new StringBuilder(null == style ? "" : style).append(";")
.append(Markup.CSS_KEY_FONTSIZE).append(":").append(H_TAG_DEFAULT_FONT_SIZE.get(tag)).append(";").toString());
}
return;
}
}
}

27
fine-itext/src/main/java/com/fr/third/v2/lowagie/text/pdf/PdfChunk.java

@ -832,6 +832,21 @@ public class PdfChunk {
public String toHtmlString() { public String toHtmlString() {
StringBuffer htmlString = new StringBuffer(); StringBuffer htmlString = new StringBuffer();
String hyperlink =getHyperlink();
if (null != hyperlink && hyperlink.length() > 0) {
htmlString.append("<a style='");
htmlString.append(getStyleAttributes()).append("'");
htmlString.append(" href='").append(hyperlink).append("'>");
if (this.isImage()) {
htmlString.append("<img src='").append(image.getSrcString()).append("'").
append(" style='width:").append(image.getPlainWidth()).append("px").
append(" height:").append(image.getPlainHeight()).append("px'").append("/>");
} else {
htmlString.append(value);
}
htmlString.append("</a>");
return htmlString.toString();
}
if (this.isImage()) { if (this.isImage()) {
htmlString.append("<img src='").append(image.getSrcString()).append("'"). htmlString.append("<img src='").append(image.getSrcString()).append("'").
append(" style='width:").append(image.getPlainWidth()).append("px"). append(" style='width:").append(image.getPlainWidth()).append("px").
@ -847,6 +862,15 @@ public class PdfChunk {
return htmlString.toString(); return htmlString.toString();
} }
public String getHyperlink() {
Object obj = this.getAttribute(Chunk.ACTION);
if (null == obj || !(obj instanceof PdfAction)) {
return null;
}
PdfObject pdfObj = ((PdfAction) obj).get(PdfName.URI);
return null == pdfObj ? null : pdfObj.toString();
}
private String getStyleAttributes(){ private String getStyleAttributes(){
StringBuffer stringBuffer = new StringBuffer(); StringBuffer stringBuffer = new StringBuffer();
dealFontStyle(stringBuffer, font.getOriFont()); dealFontStyle(stringBuffer, font.getOriFont());
@ -872,6 +896,9 @@ public class PdfChunk {
if (font.isUnderlined()) { if (font.isUnderlined()) {
s.append("text-decoration :underline;"); s.append("text-decoration :underline;");
} }
if (font.isStrikethru()) {
s.append("text-decoration :line-through;");
}
} }
public String javaColor2JSColorWithAlpha(Color var0) { public String javaColor2JSColorWithAlpha(Color var0) {

1
fine-itext/src/main/java/com/fr/third/v2/lowagie/text/pdf/PdfLine.java

@ -214,6 +214,7 @@ public class PdfLine {
// if the chunk couldn't even be truncated, we add everything, so be it // if the chunk couldn't even be truncated, we add everything, so be it
else if (overflow != null){ else if (overflow != null){
addToLine(overflow); addToLine(overflow);
width = 0;
return null; return null;
}else{ }else{
addToLine(chunk); addToLine(chunk);

2
fine-itext/src/main/java/com/fr/third/v2/lowagie/text/xml/simpleparser/SimpleXMLParser.java

@ -494,7 +494,7 @@ public final class SimpleXMLParser {
if (c == -1) { if (c == -1) {
return; return;
} }
if (c == '/' || HTMLWorker.tagsPrefixSupported.containsKey(c)) { if (c == '/' || HTMLWorker.tagsPrefixSupported.containsKey(Character.toLowerCase(c))) {
if (type == TEXT) { if (type == TEXT) {
flush(); flush();
} }

2
fine-jackson/src/main/java/com/fr/third/fasterxml/jackson/databind/type/ClassFactory.java

@ -8,4 +8,4 @@ public interface ClassFactory {
Class<?> classForName(String className) throws ClassNotFoundException; Class<?> classForName(String className) throws ClassNotFoundException;
Class<?> classForName(String className, ClassLoader classLoader) throws ClassNotFoundException; Class<?> classForName(String className, ClassLoader classLoader) throws ClassNotFoundException;
} }

3
fine-jackson/src/main/java/com/fr/third/fasterxml/jackson/databind/type/TypeFactory.java

@ -137,7 +137,7 @@ public final class TypeFactory
* ClassLoader used by this factory [databind#624]. * ClassLoader used by this factory [databind#624].
*/ */
protected final ClassLoader _classLoader; protected final ClassLoader _classLoader;
private ClassFactory classFactory; private ClassFactory classFactory;
/* /*
@ -146,6 +146,7 @@ public final class TypeFactory
/********************************************************** /**********************************************************
*/ */
public void setClassFactory(ClassFactory classFactory) { public void setClassFactory(ClassFactory classFactory) {
this.classFactory = classFactory; this.classFactory = classFactory;

7
fine-quartz/src/main/java/com/fr/third/v2/org/quartz/Scheduler.java

@ -198,6 +198,13 @@ public interface Scheduler {
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/ */
/**
* 切换指定节点id
* @param oldId 旧id
* @param newId 新id
*/
void changeAppointId(String oldId, String newId);
/** /**
* Returns the name of the <code>Scheduler</code>. * Returns the name of the <code>Scheduler</code>.
*/ */

4
fine-quartz/src/main/java/com/fr/third/v2/org/quartz/Trigger.java

@ -127,6 +127,10 @@ public interface Trigger extends Serializable, Cloneable, Comparable<Trigger> {
*/ */
public static final int DEFAULT_PRIORITY = 5; public static final int DEFAULT_PRIORITY = 5;
String getAppointId();
void setAppointId(String appointId);
public TriggerKey getKey(); public TriggerKey getKey();
public JobKey getJobKey(); public JobKey getJobKey();

9
fine-quartz/src/main/java/com/fr/third/v2/org/quartz/TriggerBuilder.java

@ -71,6 +71,7 @@ public class TriggerBuilder<T extends Trigger> {
private String calendarName; private String calendarName;
private JobKey jobKey; private JobKey jobKey;
private JobDataMap jobDataMap = new JobDataMap(); private JobDataMap jobDataMap = new JobDataMap();
private String appointId;
private ScheduleBuilder<?> scheduleBuilder = null; private ScheduleBuilder<?> scheduleBuilder = null;
@ -99,7 +100,8 @@ public class TriggerBuilder<T extends Trigger> {
if(scheduleBuilder == null) if(scheduleBuilder == null)
scheduleBuilder = SimpleScheduleBuilder.simpleSchedule(); scheduleBuilder = SimpleScheduleBuilder.simpleSchedule();
MutableTrigger trig = scheduleBuilder.build(); MutableTrigger trig = scheduleBuilder.build();
trig.setAppointId(appointId);
trig.setCalendarName(calendarName); trig.setCalendarName(calendarName);
trig.setDescription(description); trig.setDescription(description);
trig.setStartTime(startTime); trig.setStartTime(startTime);
@ -117,6 +119,11 @@ public class TriggerBuilder<T extends Trigger> {
return (T) trig; return (T) trig;
} }
public TriggerBuilder<T> appointId(String appointId) {
this.appointId = appointId;
return this;
}
/** /**
* Use a <code>TriggerKey</code> with the given name and default group to * Use a <code>TriggerKey</code> with the given name and default group to
* identify the Trigger. * identify the Trigger.

4
fine-quartz/src/main/java/com/fr/third/v2/org/quartz/core/QuartzScheduler.java

@ -860,6 +860,10 @@ public class QuartzScheduler implements RemotableQuartzScheduler {
return ft; return ft;
} }
public void changeAppointId(String oldId, String newId) {
resources.getJobStore().changeAppointId(oldId, newId);
}
/** /**
* <p> * <p>
* Schedule the given <code>{@link Trigger}</code> with the * Schedule the given <code>{@link Trigger}</code> with the

5
fine-quartz/src/main/java/com/fr/third/v2/org/quartz/impl/RemoteMBeanScheduler.java

@ -165,6 +165,11 @@ public abstract class RemoteMBeanScheduler implements Scheduler {
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/ */
@Override
public void changeAppointId(String oldId, String newId) {
// do nothing
}
/** /**
* <p> * <p>
* Returns the name of the <code>Scheduler</code>. * Returns the name of the <code>Scheduler</code>.

5
fine-quartz/src/main/java/com/fr/third/v2/org/quartz/impl/RemoteScheduler.java

@ -131,6 +131,11 @@ public class RemoteScheduler implements Scheduler {
return ex; return ex;
} }
@Override
public void changeAppointId(String oldId, String newId) {
// do nothing
}
/** /**
* <p> * <p>
* Returns the name of the <code>Scheduler</code>. * Returns the name of the <code>Scheduler</code>.

5
fine-quartz/src/main/java/com/fr/third/v2/org/quartz/impl/StdScheduler.java

@ -89,6 +89,11 @@ public class StdScheduler implements Scheduler {
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/ */
@Override
public void changeAppointId(String oldId, String newId) {
sched.changeAppointId(oldId, newId);
}
/** /**
* <p> * <p>
* Returns the name of the <code>Scheduler</code>. * Returns the name of the <code>Scheduler</code>.

5
fine-quartz/src/main/java/com/fr/third/v2/org/quartz/impl/StdSchedulerFactory.java

@ -193,6 +193,8 @@ public class StdSchedulerFactory implements SchedulerFactory {
public static final String PROP_JOB_STORE_PREFIX = "com.fr.third.v2.org.quartz.jobStore"; public static final String PROP_JOB_STORE_PREFIX = "com.fr.third.v2.org.quartz.jobStore";
public static final String PROP_JOB_STORE_CURRENT_ID = "com.fr.third.v2.org.quartz.jobStore.currentId";
public static final String PROP_JOB_STORE_LOCK_HANDLER_PREFIX = PROP_JOB_STORE_PREFIX + ".lockHandler"; public static final String PROP_JOB_STORE_LOCK_HANDLER_PREFIX = PROP_JOB_STORE_PREFIX + ".lockHandler";
public static final String PROP_JOB_STORE_LOCK_HANDLER_CLASS = PROP_JOB_STORE_LOCK_HANDLER_PREFIX + ".class"; public static final String PROP_JOB_STORE_LOCK_HANDLER_CLASS = PROP_JOB_STORE_LOCK_HANDLER_PREFIX + ".class";
@ -860,8 +862,11 @@ public class StdSchedulerFactory implements SchedulerFactory {
throw initException; throw initException;
} }
String currentId = cfg.getStringProperty(PROP_JOB_STORE_CURRENT_ID);
try { try {
js = (JobStore) loadHelper.loadClass(jsClass).newInstance(); js = (JobStore) loadHelper.loadClass(jsClass).newInstance();
js.setCurrentId(currentId);
} catch (Exception e) { } catch (Exception e) {
initException = new SchedulerException("JobStore class '" + jsClass initException = new SchedulerException("JobStore class '" + jsClass
+ "' could not be instantiated.", e); + "' could not be instantiated.", e);

2
fine-quartz/src/main/java/com/fr/third/v2/org/quartz/impl/jdbcjobstore/Constants.java

@ -105,6 +105,8 @@ public interface Constants {
String ALIAS_COL_NEXT_FIRE_TIME = "ALIAS_NXT_FR_TM"; String ALIAS_COL_NEXT_FIRE_TIME = "ALIAS_NXT_FR_TM";
String COL_APPOINT_ID= "APPOINT_ID";
// TABLE_SIMPLE_TRIGGERS columns names // TABLE_SIMPLE_TRIGGERS columns names
String COL_REPEAT_COUNT = "REPEAT_COUNT"; String COL_REPEAT_COUNT = "REPEAT_COUNT";

6
fine-quartz/src/main/java/com/fr/third/v2/org/quartz/impl/jdbcjobstore/DriverDelegate.java

@ -99,6 +99,10 @@ public interface DriverDelegate {
String newState, String oldState1, String oldState2) String newState, String oldState1, String oldState2)
throws SQLException; throws SQLException;
int updateTriggerStatesFromOtherStates(Connection conn, String newState, String oldState1, String oldState2, String oldState3) throws SQLException;
int updateTriggerAppointId(Connection conn, String oldId, String newId) throws SQLException;
/** /**
* <p> * <p>
* Get the names of all of the triggers that have misfired - according to * Get the names of all of the triggers that have misfired - according to
@ -968,6 +972,8 @@ public interface DriverDelegate {
public List<TriggerKey> selectTriggerToAcquire(Connection conn, long noLaterThan, long noEarlierThan, int maxCount) public List<TriggerKey> selectTriggerToAcquire(Connection conn, long noLaterThan, long noEarlierThan, int maxCount)
throws SQLException; throws SQLException;
List<TriggerKey> selectAppointTriggerToAcquire(Connection conn, long noLaterThan, long noEarlierThan, int maxCount, String appointId);
/** /**
* <p> * <p>
* Insert a fired trigger. * Insert a fired trigger.

56
fine-quartz/src/main/java/com/fr/third/v2/org/quartz/impl/jdbcjobstore/JobStoreSupport.java

@ -159,6 +159,8 @@ public abstract class JobStoreSupport implements JobStore, Constants {
private volatile boolean schedulerRunning = false; private volatile boolean schedulerRunning = false;
private volatile boolean shutdown = false; private volatile boolean shutdown = false;
private volatile String currentId;
/* /*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* *
@ -167,6 +169,32 @@ public abstract class JobStoreSupport implements JobStore, Constants {
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/ */
@Override
public void setCurrentId(String currentId) {
this.currentId = currentId;
}
@Override
public void changeAppointId(final String oldId, final String newId) {
try {
executeInNonManagedTXLock(
LOCK_TRIGGER_ACCESS,
new VoidTransactionCallback() {
public void executeVoid(Connection conn) throws JobPersistenceException {
try {
int rows = getDelegate().updateTriggerAppointId(conn, oldId, newId);
getLog().info("update " + rows + " triggers appointId from " + oldId + " to " + newId);
} catch (SQLException e) {
throw new JobPersistenceException("Couldn't update appointId: " + e.getMessage(), e);
}
}
}, null);
} catch (JobPersistenceException e) {
getLog().error(e.getMessage());
}
}
/** /**
* <p> * <p>
* Set the name of the <code>DataSource</code> that should be used for * Set the name of the <code>DataSource</code> that should be used for
@ -854,14 +882,14 @@ public abstract class JobStoreSupport implements JobStore, Constants {
try { try {
// update inconsistent job states // update inconsistent job states
int rows = getDelegate().updateTriggerStatesFromOtherStates(conn, int rows = getDelegate().updateTriggerStatesFromOtherStates(conn,
STATE_WAITING, STATE_ACQUIRED, STATE_BLOCKED); STATE_WAITING, STATE_ACQUIRED, STATE_BLOCKED, STATE_ERROR);
rows += getDelegate().updateTriggerStatesFromOtherStates(conn, rows += getDelegate().updateTriggerStatesFromOtherStates(conn,
STATE_PAUSED, STATE_PAUSED_BLOCKED, STATE_PAUSED_BLOCKED); STATE_PAUSED, STATE_PAUSED_BLOCKED, STATE_PAUSED_BLOCKED);
getLog().info( getLog().info(
"Freed " + rows "Freed " + rows
+ " triggers from 'acquired' / 'blocked' state."); + " triggers from 'acquired' / 'blocked' / 'error' state.");
// clean up misfired jobs // clean up misfired jobs
recoverMisfiredJobs(conn, true); recoverMisfiredJobs(conn, true);
@ -2780,6 +2808,17 @@ public abstract class JobStoreSupport implements JobStore, Constants {
}); });
} }
private void mergeKeys(List<TriggerKey> allKeys, Set<String> allKeyIds, List<TriggerKey> mergeKeys) {
if (mergeKeys != null) {
for (TriggerKey key : mergeKeys) {
if (!allKeyIds.contains(key.toString())) {
allKeys.add(key);
allKeyIds.add(key.toString());
}
}
}
}
// FUTURE_TODO: this really ought to return something like a FiredTriggerBundle, // FUTURE_TODO: this really ought to return something like a FiredTriggerBundle,
// so that the fireInstanceId doesn't have to be on the trigger... // so that the fireInstanceId doesn't have to be on the trigger...
protected List<OperableTrigger> acquireNextTrigger(Connection conn, long noLaterThan, int maxCount, long timeWindow) protected List<OperableTrigger> acquireNextTrigger(Connection conn, long noLaterThan, int maxCount, long timeWindow)
@ -2795,15 +2834,22 @@ public abstract class JobStoreSupport implements JobStore, Constants {
do { do {
currentLoopCount++; currentLoopCount++;
try { try {
List<TriggerKey> keys = getDelegate().selectTriggerToAcquire(conn, noLaterThan + timeWindow, getMisfireTime(), maxCount); long misfireTime = getMisfireTime();
List<TriggerKey> waitingKeys = getDelegate().selectTriggerToAcquire(conn, noLaterThan + timeWindow, misfireTime, maxCount);
List<TriggerKey> appointKeys = getDelegate().selectAppointTriggerToAcquire(conn, noLaterThan + timeWindow, misfireTime, maxCount, this.currentId);
List<TriggerKey> allKeys = new ArrayList<TriggerKey>();
Set<String> keyIds = new HashSet<String>();
mergeKeys(allKeys, keyIds, waitingKeys);
mergeKeys(allKeys, keyIds, appointKeys);
// No trigger is ready to fire yet. // No trigger is ready to fire yet.
if (keys == null || keys.size() == 0) if (keyIds.size() == 0)
return acquiredTriggers; return acquiredTriggers;
long batchEnd = noLaterThan; long batchEnd = noLaterThan;
for (TriggerKey triggerKey : keys) { for (TriggerKey triggerKey : allKeys) {
// If our trigger is no longer available, try a new one. // If our trigger is no longer available, try a new one.
OperableTrigger nextTrigger = retrieveTrigger(conn, triggerKey); OperableTrigger nextTrigger = retrieveTrigger(conn, triggerKey);
if (nextTrigger == null) { if (nextTrigger == null) {

1
fine-quartz/src/main/java/com/fr/third/v2/org/quartz/impl/jdbcjobstore/PointbaseDelegate.java

@ -181,6 +181,7 @@ public class PointbaseDelegate extends StdJDBCDelegate {
ps.setInt(13, trigger.getMisfireInstruction()); ps.setInt(13, trigger.getMisfireInstruction());
ps.setBinaryStream(14, bais, len); ps.setBinaryStream(14, bais, len);
ps.setInt(15, trigger.getPriority()); ps.setInt(15, trigger.getPriority());
ps.setString(16, trigger.getAppointId());
insertResult = ps.executeUpdate(); insertResult = ps.executeUpdate();

58
fine-quartz/src/main/java/com/fr/third/v2/org/quartz/impl/jdbcjobstore/StdJDBCConstants.java

@ -47,19 +47,44 @@ public interface StdJDBCConstants extends Constants {
String SCHED_NAME_SUBST = "{1}"; String SCHED_NAME_SUBST = "{1}";
// QUERIES // QUERIES
String UPDATE_TRIGGER_STATES_FROM_OTHER_STATES = "UPDATE " String UPDATE_TRIGGER_STATES_FROM_OTHER_2_STATES = "UPDATE "
+ TABLE_PREFIX_SUBST + TABLE_PREFIX_SUBST
+ TABLE_TRIGGERS + TABLE_TRIGGERS
+ " SET " + " SET "
+ COL_TRIGGER_STATE + COL_TRIGGER_STATE
+ " = ?" + " = ?"
+ " WHERE " + " WHERE "
+ COL_SCHEDULER_NAME + COL_SCHEDULER_NAME
+ " = " + SCHED_NAME_SUBST + " AND (" + " = " + SCHED_NAME_SUBST + " AND ("
+ COL_TRIGGER_STATE + COL_TRIGGER_STATE
+ " = ? OR " + " = ? OR "
+ COL_TRIGGER_STATE + " = ?)"; + COL_TRIGGER_STATE + " = ?)";
String UPDATE_TRIGGER_STATES_FROM_OTHER_3_STATES = "UPDATE "
+ TABLE_PREFIX_SUBST
+ TABLE_TRIGGERS
+ " SET "
+ COL_TRIGGER_STATE
+ " = ?"
+ " WHERE "
+ COL_SCHEDULER_NAME
+ " = " + SCHED_NAME_SUBST + " AND ("
+ COL_TRIGGER_STATE
+ " = ? OR "
+ COL_TRIGGER_STATE
+ " = ? OR "
+ COL_TRIGGER_STATE + " = ?)";
String UPDATE_TRIGGER_APPOINT_ID = "UPDATE "
+ TABLE_PREFIX_SUBST
+ TABLE_TRIGGERS
+ " SET "
+ COL_APPOINT_ID
+ " = ?"
+ " WHERE "
+ COL_APPOINT_ID
+ " = ?";
String SELECT_MISFIRED_TRIGGERS = "SELECT * FROM " String SELECT_MISFIRED_TRIGGERS = "SELECT * FROM "
+ TABLE_PREFIX_SUBST + TABLE_TRIGGERS + " WHERE " + TABLE_PREFIX_SUBST + TABLE_TRIGGERS + " WHERE "
+ COL_SCHEDULER_NAME + " = " + SCHED_NAME_SUBST + COL_SCHEDULER_NAME + " = " + SCHED_NAME_SUBST
@ -212,8 +237,8 @@ public interface StdJDBCConstants extends Constants {
+ ", " + COL_NEXT_FIRE_TIME + ", " + COL_PREV_FIRE_TIME + ", " + ", " + COL_NEXT_FIRE_TIME + ", " + COL_PREV_FIRE_TIME + ", "
+ COL_TRIGGER_STATE + ", " + COL_TRIGGER_TYPE + ", " + COL_TRIGGER_STATE + ", " + COL_TRIGGER_TYPE + ", "
+ COL_START_TIME + ", " + COL_END_TIME + ", " + COL_CALENDAR_NAME + COL_START_TIME + ", " + COL_END_TIME + ", " + COL_CALENDAR_NAME
+ ", " + COL_MISFIRE_INSTRUCTION + ", " + COL_JOB_DATAMAP + ", " + COL_PRIORITY + ") " + ", " + COL_MISFIRE_INSTRUCTION + ", " + COL_JOB_DATAMAP + ", " + COL_PRIORITY + ", " + COL_APPOINT_ID + ") "
+ " VALUES(" + SCHED_NAME_SUBST + ", ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + " VALUES(" + SCHED_NAME_SUBST + ", ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
String INSERT_SIMPLE_TRIGGER = "INSERT INTO " String INSERT_SIMPLE_TRIGGER = "INSERT INTO "
+ TABLE_PREFIX_SUBST + TABLE_SIMPLE_TRIGGERS + " (" + TABLE_PREFIX_SUBST + TABLE_SIMPLE_TRIGGERS + " ("
@ -507,13 +532,24 @@ public interface StdJDBCConstants extends Constants {
+ " AND " + COL_TRIGGER_STATE + " = ? AND " + COL_NEXT_FIRE_TIME + " = ?"; + " AND " + COL_TRIGGER_STATE + " = ? AND " + COL_NEXT_FIRE_TIME + " = ?";
String SELECT_NEXT_TRIGGER_TO_ACQUIRE = "SELECT " String SELECT_NEXT_TRIGGER_TO_ACQUIRE = "SELECT "
+ COL_TRIGGER_NAME + ", " + COL_TRIGGER_GROUP + ", " + COL_TRIGGER_NAME + ", " + COL_TRIGGER_GROUP + ", "
+ COL_NEXT_FIRE_TIME + ", " + COL_PRIORITY + " FROM " + COL_NEXT_FIRE_TIME + ", " + COL_PRIORITY + " FROM "
+ TABLE_PREFIX_SUBST + TABLE_TRIGGERS + " WHERE " + TABLE_PREFIX_SUBST + TABLE_TRIGGERS + " WHERE "
+ COL_SCHEDULER_NAME + " = " + SCHED_NAME_SUBST + COL_SCHEDULER_NAME + " = " + SCHED_NAME_SUBST
+ " AND " + COL_TRIGGER_STATE + " = ? AND " + COL_NEXT_FIRE_TIME + " <= ? " + " AND " + COL_APPOINT_ID + " IS NULL"
+ "AND (" + COL_MISFIRE_INSTRUCTION + " = -1 OR (" +COL_MISFIRE_INSTRUCTION+ " != -1 AND "+ COL_NEXT_FIRE_TIME + " >= ?)) " + " AND " + COL_TRIGGER_STATE + " = ? AND " + COL_NEXT_FIRE_TIME + " <= ? "
+ "ORDER BY "+ COL_NEXT_FIRE_TIME + " ASC, " + COL_PRIORITY + " DESC"; + "AND (" + COL_MISFIRE_INSTRUCTION + " = -1 OR (" + COL_MISFIRE_INSTRUCTION + " != -1 AND " + COL_NEXT_FIRE_TIME + " >= ?)) "
+ "ORDER BY " + COL_NEXT_FIRE_TIME + " ASC, " + COL_PRIORITY + " DESC";
String SELECT_NEXT_APPOINT_TRIGGER_TO_ACQUIRE = "SELECT "
+ COL_TRIGGER_NAME + ", " + COL_TRIGGER_GROUP + ", "
+ COL_NEXT_FIRE_TIME + ", " + COL_PRIORITY + " FROM "
+ TABLE_PREFIX_SUBST + TABLE_TRIGGERS + " WHERE "
+ COL_SCHEDULER_NAME + " = " + SCHED_NAME_SUBST
+ " AND " + COL_APPOINT_ID + " = ?"
+ " AND " + COL_TRIGGER_STATE + " = ? AND " + COL_NEXT_FIRE_TIME + " <= ? "
+ "AND (" + COL_MISFIRE_INSTRUCTION + " = -1 OR (" + COL_MISFIRE_INSTRUCTION + " != -1 AND " + COL_NEXT_FIRE_TIME + " >= ?)) "
+ "ORDER BY " + COL_NEXT_FIRE_TIME + " ASC, " + COL_PRIORITY + " DESC";
String INSERT_FIRED_TRIGGER = "INSERT INTO " String INSERT_FIRED_TRIGGER = "INSERT INTO "

70
fine-quartz/src/main/java/com/fr/third/v2/org/quartz/impl/jdbcjobstore/StdJDBCDelegate.java

@ -227,8 +227,7 @@ public class StdJDBCDelegate implements DriverDelegate, StdJDBCConstants {
PreparedStatement ps = null; PreparedStatement ps = null;
try { try {
ps = conn ps = conn.prepareStatement(rtp(UPDATE_TRIGGER_STATES_FROM_OTHER_2_STATES));
.prepareStatement(rtp(UPDATE_TRIGGER_STATES_FROM_OTHER_STATES));
ps.setString(1, newState); ps.setString(1, newState);
ps.setString(2, oldState1); ps.setString(2, oldState1);
ps.setString(3, oldState2); ps.setString(3, oldState2);
@ -238,6 +237,38 @@ public class StdJDBCDelegate implements DriverDelegate, StdJDBCConstants {
} }
} }
@Override
public int updateTriggerStatesFromOtherStates(Connection conn, String newState, String oldState1, String oldState2, String oldState3) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(rtp(UPDATE_TRIGGER_STATES_FROM_OTHER_3_STATES));
ps.setString(1, newState);
ps.setString(2, oldState1);
ps.setString(3, oldState2);
ps.setString(4, oldState3);
return ps.executeUpdate();
} finally {
closeStatement(ps);
}
}
@Override
public int updateTriggerAppointId(Connection conn, String oldId, String newId) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(rtp(UPDATE_TRIGGER_APPOINT_ID));
ps.setString(1, newId);
ps.setString(2, oldId);
return ps.executeUpdate();
} finally {
closeStatement(ps);
}
}
/** /**
* <p> * <p>
* Get the names of all of the triggers that have misfired. * Get the names of all of the triggers that have misfired.
@ -1088,6 +1119,7 @@ public class StdJDBCDelegate implements DriverDelegate, StdJDBCConstants {
ps.setInt(13, trigger.getMisfireInstruction()); ps.setInt(13, trigger.getMisfireInstruction());
setBytes(ps, 14, baos); setBytes(ps, 14, baos);
ps.setInt(15, trigger.getPriority()); ps.setInt(15, trigger.getPriority());
ps.setString(16, trigger.getAppointId());
insertResult = ps.executeUpdate(); insertResult = ps.executeUpdate();
@ -2624,6 +2656,40 @@ public class StdJDBCDelegate implements DriverDelegate, StdJDBCConstants {
} }
} }
public List<TriggerKey> selectAppointTriggerToAcquire(Connection conn, long noLaterThan, long noEarlierThan, int maxCount, String appointId) {
PreparedStatement ps = null;
ResultSet rs = null;
List<TriggerKey> nextTriggers = new LinkedList<TriggerKey>();
try {
ps = conn.prepareStatement(rtp(SELECT_NEXT_APPOINT_TRIGGER_TO_ACQUIRE));
if (maxCount < 1)
maxCount = 1;
ps.setMaxRows(maxCount);
ps.setFetchSize(maxCount);
ps.setString(1, appointId);
ps.setString(2, STATE_WAITING);
ps.setBigDecimal(3, new BigDecimal(String.valueOf(noLaterThan)));
ps.setBigDecimal(4, new BigDecimal(String.valueOf(noEarlierThan)));
rs = ps.executeQuery();
while (rs.next() && nextTriggers.size() <= maxCount) {
nextTriggers.add(TriggerKey.triggerKey(
rs.getString(COL_TRIGGER_NAME),
rs.getString(COL_TRIGGER_GROUP)));
}
return nextTriggers;
} catch (Exception e) {
logger.error(e.getMessage(), e);
return null;
} finally {
closeResultSet(rs);
closeStatement(ps);
}
}
/** /**
* <p> * <p>
* Insert a fired trigger. * Insert a fired trigger.

1
fine-quartz/src/main/java/com/fr/third/v2/org/quartz/impl/jdbcjobstore/oracle/OracleDelegate.java

@ -318,6 +318,7 @@ public class OracleDelegate extends StdJDBCDelegate {
ps.setInt(13, trigger.getMisfireInstruction()); ps.setInt(13, trigger.getMisfireInstruction());
ps.setBinaryStream(14, null, 0); ps.setBinaryStream(14, null, 0);
ps.setInt(15, trigger.getPriority()); ps.setInt(15, trigger.getPriority());
ps.setString(16, trigger.getAppointId());
insertResult = ps.executeUpdate(); insertResult = ps.executeUpdate();

33
fine-quartz/src/main/java/com/fr/third/v2/org/quartz/impl/triggers/AbstractTrigger.java

@ -75,6 +75,8 @@ public abstract class AbstractTrigger<T extends Trigger> implements OperableTrig
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/ */
private String appointId;
private String name; private String name;
private String group = Scheduler.DEFAULT_GROUP; private String group = Scheduler.DEFAULT_GROUP;
@ -251,6 +253,16 @@ public abstract class AbstractTrigger<T extends Trigger> implements OperableTrig
this.key = null; this.key = null;
} }
@Override
public String getAppointId() {
return this.appointId;
}
@Override
public void setAppointId(String appointId) {
this.appointId = appointId;
}
public void setKey(TriggerKey key) { public void setKey(TriggerKey key) {
setName(key.getName()); setName(key.getName());
setGroup(key.getGroup()); setGroup(key.getGroup());
@ -873,18 +885,19 @@ public abstract class AbstractTrigger<T extends Trigger> implements OperableTrig
} }
return copy; return copy;
} }
public TriggerBuilder<T> getTriggerBuilder() { public TriggerBuilder<T> getTriggerBuilder() {
return TriggerBuilder.newTrigger() return TriggerBuilder.newTrigger()
.forJob(getJobKey()) .appointId(getAppointId())
.modifiedByCalendar(getCalendarName()) .forJob(getJobKey())
.usingJobData(getJobDataMap()) .modifiedByCalendar(getCalendarName())
.withDescription(getDescription()) .usingJobData(getJobDataMap())
.endAt(getEndTime()) .withDescription(getDescription())
.withIdentity(getKey()) .endAt(getEndTime())
.withPriority(getPriority()) .withIdentity(getKey())
.startAt(getStartTime()) .withPriority(getPriority())
.withSchedule(getScheduleBuilder()); .startAt(getStartTime())
.withSchedule(getScheduleBuilder());
} }
public abstract ScheduleBuilder<T> getScheduleBuilder(); public abstract ScheduleBuilder<T> getScheduleBuilder();

10
fine-quartz/src/main/java/com/fr/third/v2/org/quartz/simpl/RAMJobStore.java

@ -139,6 +139,16 @@ public class RAMJobStore implements JobStore {
return log; return log;
} }
@Override
public void setCurrentId(String currentId) {
//do nothing
}
@Override
public void changeAppointId(String oldId, String newId) {
//do nothing
}
/** /**
* <p> * <p>
* Called by the QuartzScheduler before the <code>JobStore</code> is * Called by the QuartzScheduler before the <code>JobStore</code> is

13
fine-quartz/src/main/java/com/fr/third/v2/org/quartz/spi/JobStore.java

@ -68,6 +68,19 @@ public interface JobStore {
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/ */
/**
* 设置当前节点id
*/
void setCurrentId(String currentId);
/**
* 切换指定节点id
* @param oldId 旧id
* @param newId 新id
*/
void changeAppointId(String oldId, String newId);
/** /**
* Called by the QuartzScheduler before the <code>JobStore</code> is * Called by the QuartzScheduler before the <code>JobStore</code> is
* used, in order to give the it a chance to initialize. * used, in order to give the it a chance to initialize.

2
fine-spring/pom.xml

@ -65,7 +65,7 @@
<artifactId>fine-javax-annotation</artifactId> <artifactId>fine-javax-annotation</artifactId>
<version>${revision}</version> <version>${revision}</version>
</dependency> </dependency>
<!-->以下是lib的本地jar包依赖<--> <!-->以下是lib的本地jar包依赖<-->
<dependency> <dependency>
<groupId>com.fr.third</groupId> <groupId>com.fr.third</groupId>
<artifactId>aopalliance</artifactId> <artifactId>aopalliance</artifactId>

23
pom.xml

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<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>
<modules>
<module>fine-hibernate</module>
<module>fine-druid</module>
</modules>>
<parent>
<groupId>com.fr.maven</groupId>
<artifactId>finereport-maven</artifactId>
<version>10.0</version>
<relativePath>../finereport-maven</relativePath>
</parent>
<groupId>com.fr.third</groupId>
<artifactId>base-third-code</artifactId>
<version>${branch}</version>
<packaging>pom</packaging>
</project>
Loading…
Cancel
Save