diff --git a/group09/41689722.eulerlcs/2.code/jmr-01-aggregator/pom.xml b/group09/41689722.eulerlcs/2.code/jmr-01-aggregator/pom.xml
index be065e6a95..b04166b31c 100644
--- a/group09/41689722.eulerlcs/2.code/jmr-01-aggregator/pom.xml
+++ b/group09/41689722.eulerlcs/2.code/jmr-01-aggregator/pom.xml
@@ -12,5 +12,6 @@
../jmr-11-challenge
../jmr-61-170226-collection
../jmr-61-170305-litestruts
+ ../jmr-61-170312-multiThreadDownload
\ No newline at end of file
diff --git a/group09/41689722.eulerlcs/2.code/jmr-11-challenge/data/xmlparser/app-config.xml b/group09/41689722.eulerlcs/2.code/jmr-11-challenge/data/xmlparser/app-config.xml
new file mode 100644
index 0000000000..e989327e9d
--- /dev/null
+++ b/group09/41689722.eulerlcs/2.code/jmr-11-challenge/data/xmlparser/app-config.xml
@@ -0,0 +1,12 @@
+
+
+ a
+ b
+ c
+ d
+ e
+ f
+ g
+ h
+ i
+
diff --git a/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/coderising/litestruts/LoginAction.java b/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/coderising/litestruts/LoginAction.java
deleted file mode 100644
index dcdbe226ed..0000000000
--- a/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/coderising/litestruts/LoginAction.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.coderising.litestruts;
-
-/**
- * 这是一个用来展示登录的业务类, 其中的用户名和密码都是硬编码的。
- * @author liuxin
- *
- */
-public class LoginAction{
- private String name ;
- private String password;
- private String message;
-
- public String getName() {
- return name;
- }
-
- public String getPassword() {
- return password;
- }
-
- public String execute(){
- if("test".equals(name) && "1234".equals(password)){
- this.message = "login successful";
- return "success";
- }
- this.message = "login failed,please check your user/pwd";
- return "fail";
- }
-
- public void setName(String name){
- this.name = name;
- }
- public void setPassword(String password){
- this.password = password;
- }
- public String getMessage(){
- return this.message;
- }
-}
diff --git a/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/coderising/litestruts/Struts.java b/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/coderising/litestruts/Struts.java
deleted file mode 100644
index 85e2e22de3..0000000000
--- a/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/coderising/litestruts/Struts.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.coderising.litestruts;
-
-import java.util.Map;
-
-
-
-public class Struts {
-
- public static View runAction(String actionName, Map parameters) {
-
- /*
-
- 0. 读取配置文件struts.xml
-
- 1. 根据actionName找到相对应的class , 例如LoginAction, 通过反射实例化(创建对象)
- 据parameters中的数据,调用对象的setter方法, 例如parameters中的数据是
- ("name"="test" , "password"="1234") ,
- 那就应该调用 setName和setPassword方法
-
- 2. 通过反射调用对象的exectue 方法, 并获得返回值,例如"success"
-
- 3. 通过反射找到对象的所有getter方法(例如 getMessage),
- 通过反射来调用, 把值和属性形成一个HashMap , 例如 {"message": "登录成功"} ,
- 放到View对象的parameters
-
- 4. 根据struts.xml中的 配置,以及execute的返回值, 确定哪一个jsp,
- 放到View对象的jsp字段中。
-
- */
-
- return null;
- }
-
-}
diff --git a/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/coderising/litestruts/StrutsTest.java b/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/coderising/litestruts/StrutsTest.java
deleted file mode 100644
index b8c81faf3c..0000000000
--- a/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/coderising/litestruts/StrutsTest.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.coderising.litestruts;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-
-
-
-
-public class StrutsTest {
-
- @Test
- public void testLoginActionSuccess() {
-
- String actionName = "login";
-
- Map params = new HashMap();
- params.put("name","test");
- params.put("password","1234");
-
-
- View view = Struts.runAction(actionName,params);
-
- Assert.assertEquals("/jsp/homepage.jsp", view.getJsp());
- Assert.assertEquals("login successful", view.getParameters().get("message"));
- }
-
- @Test
- public void testLoginActionFailed() {
- String actionName = "login";
- Map params = new HashMap();
- params.put("name","test");
- params.put("password","123456"); //密码和预设的不一致
-
- View view = Struts.runAction(actionName,params);
-
- Assert.assertEquals("/jsp/showLogin.jsp", view.getJsp());
- Assert.assertEquals("login failed,please check your user/pwd", view.getParameters().get("message"));
- }
-}
diff --git a/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/github/eulerlcs/jmr/challenge/xmlparser/jaxb/AppConfig.java b/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/github/eulerlcs/jmr/challenge/xmlparser/jaxb/AppConfig.java
new file mode 100644
index 0000000000..c50bce4a15
--- /dev/null
+++ b/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/github/eulerlcs/jmr/challenge/xmlparser/jaxb/AppConfig.java
@@ -0,0 +1,29 @@
+package com.github.eulerlcs.jmr.challenge.xmlparser.jaxb;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import lombok.Getter;
+
+@Getter
+@XmlRootElement(name = "app-config")
+public class AppConfig {
+ @XmlElement(name = "input-path")
+ private String inputPath;
+ @XmlElement(name = "input-look-subfolder")
+ private boolean inputLookSubfolder;
+ @XmlElement(name = "input-encode")
+ private String inputEncode;
+ @XmlElement(name = "output-path")
+ private String outputPath;
+ @XmlElement(name = "output-by-package-tree")
+ private boolean outputByPackageTree;
+ @XmlElement(name = "output-prefix")
+ private String outputPrefix;
+ @XmlElement(name = "output-subfix")
+ private String outputSubfix;
+ @XmlElement(name = "output-encode")
+ private String outputEncode;
+ @XmlElement(name = "output-package-name")
+ private String outputPackageName;
+}
diff --git a/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/github/eulerlcs/jmr/challenge/xmlparser/jaxb/Driver.java b/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/github/eulerlcs/jmr/challenge/xmlparser/jaxb/Driver.java
new file mode 100644
index 0000000000..15c5686e2e
--- /dev/null
+++ b/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/github/eulerlcs/jmr/challenge/xmlparser/jaxb/Driver.java
@@ -0,0 +1,20 @@
+package com.github.eulerlcs.jmr.challenge.xmlparser.jaxb;
+
+import java.io.File;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Driver {
+ private final static Logger log = LoggerFactory.getLogger(Driver.class);
+
+ public static void main(String[] args) {
+ File xml = new File("data//xmlparser", "hello.xml");
+ Hello hello = JaxbParser.loadAppConfig(xml, Hello.class);
+ log.debug("hello.value=[{}]", hello.getValue());
+
+ xml = new File("data//xmlparser", "app-config.xml");
+ AppConfig appConfig = JaxbParser.loadAppConfig(xml, AppConfig.class);
+ log.debug("process-args.InputPath=[{}] ", appConfig.getInputPath());
+ }
+}
diff --git a/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/github/eulerlcs/jmr/challenge/xmlparser/jaxb/Hello.java b/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/github/eulerlcs/jmr/challenge/xmlparser/jaxb/Hello.java
new file mode 100644
index 0000000000..5bad90241e
--- /dev/null
+++ b/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/github/eulerlcs/jmr/challenge/xmlparser/jaxb/Hello.java
@@ -0,0 +1,22 @@
+package com.github.eulerlcs.jmr.challenge.xmlparser.jaxb;
+
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.github.eulerlcs.jmr.challenge.xmlparser.digester.entity.HelloFile;
+
+import lombok.Getter;
+
+@Getter
+@XmlRootElement(name = "files")
+public class Hello {
+ @XmlAttribute
+ private String project;
+ @XmlAttribute
+ private String value;
+ @XmlElement(name = "file")
+ private List files;
+}
diff --git a/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/github/eulerlcs/jmr/challenge/xmlparser/jaxb/HelloFile.java b/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/github/eulerlcs/jmr/challenge/xmlparser/jaxb/HelloFile.java
new file mode 100644
index 0000000000..c5bdd127f1
--- /dev/null
+++ b/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/github/eulerlcs/jmr/challenge/xmlparser/jaxb/HelloFile.java
@@ -0,0 +1,14 @@
+package com.github.eulerlcs.jmr.challenge.xmlparser.jaxb;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlValue;
+
+import lombok.Getter;
+
+@Getter
+public class HelloFile {
+ @XmlAttribute(name = "dir")
+ private String path;
+ @XmlValue
+ private String name;
+}
\ No newline at end of file
diff --git a/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/github/eulerlcs/jmr/challenge/xmlparser/jaxb/JaxbParser.java b/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/github/eulerlcs/jmr/challenge/xmlparser/jaxb/JaxbParser.java
new file mode 100644
index 0000000000..720f524426
--- /dev/null
+++ b/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/github/eulerlcs/jmr/challenge/xmlparser/jaxb/JaxbParser.java
@@ -0,0 +1,22 @@
+package com.github.eulerlcs.jmr.challenge.xmlparser.jaxb;
+
+import java.io.File;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Unmarshaller;
+
+/* jaxb: Java Architecture for XML Binding */
+public class JaxbParser {
+ @SuppressWarnings("unchecked")
+ public static E loadAppConfig(File xml, Class clazz) {
+ E entity = null;
+ try {
+ JAXBContext jc = JAXBContext.newInstance(clazz);
+ Unmarshaller u = jc.createUnmarshaller();
+ entity = (E) u.unmarshal(xml);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return entity;
+ }
+}
diff --git a/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/github/eulerlcs/jmr/challenge/xmlparser/sax/Driver.java b/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/github/eulerlcs/jmr/challenge/xmlparser/sax/Driver.java
new file mode 100644
index 0000000000..d15739c5c9
--- /dev/null
+++ b/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/github/eulerlcs/jmr/challenge/xmlparser/sax/Driver.java
@@ -0,0 +1,19 @@
+package com.github.eulerlcs.jmr.challenge.xmlparser.sax;
+
+import java.io.File;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+public class Driver {
+ public static void main(String[] args) {
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ File xml = new File("data//xmlparser", "hello.xml");
+ try {
+ SAXParser parser = factory.newSAXParser();
+ parser.parse(xml, new HelloSaxParser());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/github/eulerlcs/jmr/challenge/xmlparser/sax/HelloSaxParser.java b/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/github/eulerlcs/jmr/challenge/xmlparser/sax/HelloSaxParser.java
new file mode 100644
index 0000000000..26cc926b11
--- /dev/null
+++ b/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/github/eulerlcs/jmr/challenge/xmlparser/sax/HelloSaxParser.java
@@ -0,0 +1,42 @@
+package com.github.eulerlcs.jmr.challenge.xmlparser.sax;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/* sax: simple api for xml */
+public class HelloSaxParser extends DefaultHandler {
+ protected static Logger log = LoggerFactory.getLogger(HelloSaxParser.class);
+
+ @Override
+ public void startDocument() throws SAXException {
+ super.startDocument();
+ log.debug("sax startDocument");
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+ super.startElement(uri, localName, qName, attributes);
+ log.debug("sax startElement qName: [{}]", qName);
+ }
+
+ @Override
+ public void characters(char[] ch, int start, int length) throws SAXException {
+ super.characters(ch, start, length);
+ log.debug("sax characters: [{}]", new String(ch, start, length));
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+ super.endElement(uri, localName, qName);
+ log.debug("sax endElement qName: [{}]", qName);
+ }
+
+ @Override
+ public void endDocument() throws SAXException {
+ super.endDocument();
+ log.debug("sax endDocument");
+ }
+}
\ No newline at end of file
diff --git a/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/coderising/litestruts/struts.xml b/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/data/struts.xml
similarity index 62%
rename from group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/coderising/litestruts/struts.xml
rename to group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/data/struts.xml
index dd598a3664..a7a77b73df 100644
--- a/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/coderising/litestruts/struts.xml
+++ b/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/data/struts.xml
@@ -1,10 +1,10 @@
-
+
/jsp/homepage.jsp
/jsp/showLogin.jsp
-
+
/jsp/welcome.jsp
/jsp/error.jsp
diff --git a/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/action/LoginAction.java b/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/action/LoginAction.java
new file mode 100644
index 0000000000..4d9af132ac
--- /dev/null
+++ b/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/action/LoginAction.java
@@ -0,0 +1,30 @@
+package com.github.eulerlcs.jmr.litestruts.action;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 这是一个用来展示登录的业务类, 其中的用户名和密码都是硬编码的。
+ *
+ * @author liuxin
+ *
+ */
+public class LoginAction {
+ @Setter
+ @Getter
+ private String name;
+ @Setter
+ @Getter
+ private String password;
+ @Getter
+ private String message;
+
+ public String execute() {
+ if ("test".equals(name) && "1234".equals(password)) {
+ this.message = "login successful";
+ return "success";
+ }
+ this.message = "login failed,please check your user/pwd";
+ return "fail";
+ }
+}
diff --git a/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/action/LogoutAction.java b/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/action/LogoutAction.java
new file mode 100644
index 0000000000..119e74e3e9
--- /dev/null
+++ b/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/action/LogoutAction.java
@@ -0,0 +1,30 @@
+package com.github.eulerlcs.jmr.litestruts.action;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 这是一个用来展示登录的业务类, 其中的用户名和密码都是硬编码的。
+ *
+ * @author liuxin
+ *
+ */
+public class LogoutAction {
+ @Setter
+ @Getter
+ private String name;
+ @Setter
+ @Getter
+ private String password;
+ @Getter
+ private String message;
+
+ public String execute() {
+ if ("test".equals(name) && "1234".equals(password)) {
+ this.message = "login successful";
+ return "success";
+ }
+ this.message = "login failed,please check your user/pwd";
+ return "error";
+ }
+}
diff --git a/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/util/ArrayUtil.java b/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/algorithm/ArrayUtil.java
similarity index 99%
rename from group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/util/ArrayUtil.java
rename to group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/algorithm/ArrayUtil.java
index 636d0b1789..36894f6e5b 100644
--- a/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/util/ArrayUtil.java
+++ b/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/algorithm/ArrayUtil.java
@@ -1,7 +1,7 @@
/**
* 问题点: 没写注释,代码比较难读。尤其 merge方法。
*/
-package com.github.eulerlcs.jmr.litestruts.util;
+package com.github.eulerlcs.jmr.litestruts.algorithm;
import java.util.Arrays;
diff --git a/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/core/Struts.java b/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/core/Struts.java
new file mode 100644
index 0000000000..459abaae99
--- /dev/null
+++ b/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/core/Struts.java
@@ -0,0 +1,200 @@
+package com.github.eulerlcs.jmr.litestruts.core;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.digester.Digester;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.SAXException;
+
+import com.github.eulerlcs.jmr.litestruts.degister.StrutsConfig;
+import com.github.eulerlcs.jmr.litestruts.degister.StrutsDigester;
+
+/**
+ *
+ * - 读取配置文件struts.xml
+ * - 根据actionName找到相对应的class , 例如LoginAction, 通过反射实例化(创建对象)
+ * 据parameters中的数据,调用对象的setter方法, 例如parameters中的数据是 ("name"="test" ,
+ * "password"="1234") , 那就应该调用 setName和setPassword方法
+ * - 通过反射调用对象的exectue 方法, 并获得返回值,例如"success"
+ * - 通过反射找到对象的所有getter方法(例如 getMessage), 通过反射来调用, 把值和属性形成一个HashMap , 例如
+ * {"message": "登录成功"} , 放到View对象的parameters
+ * - 根据struts.xml中的 配置,以及execute的返回值, 确定哪一个jsp, 放到View对象的jsp字段中。
+ *
+ */
+public class Struts {
+ private final static Logger log = LoggerFactory.getLogger(Struts.class);
+ private static StrutsConfig config = null;
+
+ public static View runAction(String actionName, Map parameters) {
+ /*
+ * 0. 读取配置文件struts.xml
+ *
+ * 1. 根据actionName找到相对应的class , 例如LoginAction, 通过反射实例化(创建对象)
+ * 据parameters中的数据,调用对象的setter方法, 例如parameters中的数据是 ("name"="test" ,
+ * "password"="1234") , 那就应该调用 setName和setPassword方法
+ *
+ * 2. 通过反射调用对象的exectue 方法, 并获得返回值,例如"success"
+ *
+ * 3. 通过反射找到对象的所有getter方法(例如 getMessage), 通过反射来调用, 把值和属性形成一个HashMap , 例如
+ * {"message": "登录成功"} , 放到View对象的parameters
+ *
+ * 4. 根据struts.xml中的 配置,以及execute的返回值, 确定哪一个jsp,
+ * 放到View对象的jsp字段中。
+ *
+ */
+
+ // 0.
+ getConfig();
+
+ // 1.1.
+ Object object = createInstance(actionName);
+ if (object == null) {
+ return null;
+ }
+ // 1.2.
+ if (!prepareParameters(object, parameters)) {
+ return null;
+ }
+ // 2.
+ String viewId = execute(object);
+ if (viewId == null) {
+ return null;
+ }
+ // 3.
+ View view = biuldView(object);
+ if (view == null) {
+ return null;
+ }
+
+ // 4.
+ String uri = config.getActionMap().get(actionName).getResults().get(viewId).getUrl();
+ view.setJsp(uri);
+
+ return view;
+ }
+
+ private static StrutsConfig getConfig() {
+ if (config != null) {
+ return config;
+ }
+
+ Digester d = StrutsDigester.newInstance();
+ try {
+ File file = new File("data", "struts.xml");
+ config = (StrutsConfig) d.parse(file);
+ } catch (IOException | SAXException e) {
+ log.error("getConfig", e);
+ System.exit(1);
+ }
+
+ return config;
+ }
+
+ private static Object createInstance(String actionName) {
+ if (actionName == null) {
+ return null;
+ }
+
+ String className = config.getActionMap().get(actionName).getClazz();
+ Object object = null;
+ try {
+ Class> clazz = Class.forName(className);
+ object = clazz.newInstance();
+ } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
+ log.error("createInstance", e);
+ }
+
+ return object;
+ }
+
+ private static boolean prepareParameters(Object object, Map parameters) {
+ if (parameters == null || parameters.size() == 0) {
+ return true;
+ }
+
+ Class> clazz = object.getClass();
+ Method setter = null;
+
+ try {
+ for (String key : parameters.keySet()) {
+ setter = clazz.getMethod(biuldSetterName(key), String.class);
+ setter.setAccessible(true);
+ setter.invoke(object, parameters.get(key));
+ }
+ } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException
+ | InvocationTargetException e) {
+ log.error("prepareParameters", e);
+ return false;
+ }
+
+ return true;
+ }
+
+ private static String biuldSetterName(String name) {
+ String setterName = "set";
+ setterName += name.substring(0, 1).toUpperCase() + name.substring(1);
+ return setterName;
+
+ }
+
+ private static String debiuldGetterName(String getterName) {
+ if (getterName == null || getterName.length() <= 3) {
+ return null;
+ }
+ if (!getterName.substring(0, 3).equals("get")) {
+ return null;
+ }
+
+ String name = getterName.substring(3, 4).toLowerCase() + getterName.substring(4);
+ return name;
+ }
+
+ private static String execute(Object object) {
+ final String METHOD_EXECUTE = "execute";
+ String viewId = null;
+
+ Class> clazz = object.getClass();
+ try {
+ Method method = clazz.getMethod(METHOD_EXECUTE);
+ viewId = (String) method.invoke(object);
+ } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException
+ | InvocationTargetException e) {
+ log.error("execute", e);
+ return viewId;
+ }
+
+ return viewId;
+ }
+
+ private static View biuldView(Object object) {
+ View view = new View();
+ Map parameters = new HashMap<>();
+
+ Class> clazz = object.getClass();
+ Method[] methods;
+ try {
+ methods = clazz.getMethods();
+ for (Method method : methods) {
+ String name = debiuldGetterName(method.getName());
+ if (name == null) {
+ continue;
+ }
+ Object value = method.invoke(object);
+ parameters.put(name, value);
+ }
+
+ view.setParameters(parameters);
+ } catch (SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+ log.error("biuldResult", e);
+ return null;
+ }
+
+ return view;
+ }
+}
diff --git a/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/coderising/litestruts/View.java b/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/core/View.java
similarity index 55%
rename from group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/coderising/litestruts/View.java
rename to group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/core/View.java
index 07df2a5dab..0aa18d5f54 100644
--- a/group09/41689722.eulerlcs/2.code/jmr-11-challenge/src/main/java/com/coderising/litestruts/View.java
+++ b/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/core/View.java
@@ -1,22 +1,25 @@
-package com.coderising.litestruts;
+package com.github.eulerlcs.jmr.litestruts.core;
import java.util.Map;
public class View {
private String jsp;
- private Map parameters;
-
+ private Map parameters;
+
public String getJsp() {
return jsp;
}
+
public View setJsp(String jsp) {
this.jsp = jsp;
return this;
}
- public Map getParameters() {
+
+ public Map getParameters() {
return parameters;
}
- public View setParameters(Map parameters) {
+
+ public View setParameters(Map parameters) {
this.parameters = parameters;
return this;
}
diff --git a/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/degister/StrutsAction.java b/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/degister/StrutsAction.java
new file mode 100644
index 0000000000..336f594241
--- /dev/null
+++ b/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/degister/StrutsAction.java
@@ -0,0 +1,22 @@
+package com.github.eulerlcs.jmr.litestruts.degister;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import lombok.Getter;
+import lombok.Setter;
+
+public class StrutsAction {
+ @Getter
+ @Setter
+ private String name;
+ @Getter
+ @Setter
+ private String clazz;
+ @Getter
+ private Map results = new HashMap<>();
+
+ public void addResult(StrutsActionResult result) {
+ results.put(result.getName(), result);
+ }
+}
diff --git a/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/degister/StrutsActionResult.java b/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/degister/StrutsActionResult.java
new file mode 100644
index 0000000000..64247d4aba
--- /dev/null
+++ b/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/degister/StrutsActionResult.java
@@ -0,0 +1,13 @@
+package com.github.eulerlcs.jmr.litestruts.degister;
+
+import lombok.Getter;
+import lombok.Setter;
+
+public class StrutsActionResult {
+ @Getter
+ @Setter
+ private String name;
+ @Getter
+ @Setter
+ private String url;
+}
diff --git a/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/degister/StrutsActionRulerSet.java b/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/degister/StrutsActionRulerSet.java
new file mode 100644
index 0000000000..567f4c7ef1
--- /dev/null
+++ b/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/degister/StrutsActionRulerSet.java
@@ -0,0 +1,30 @@
+package com.github.eulerlcs.jmr.litestruts.degister;
+
+import org.apache.commons.digester.Digester;
+import org.apache.commons.digester.RuleSetBase;
+
+final class StrutsActionRulerSet extends RuleSetBase {
+ protected String prefix = null;
+
+ public StrutsActionRulerSet() {
+ this("");
+ }
+
+ public StrutsActionRulerSet(String prefix) {
+ super();
+ this.namespaceURI = null;
+ this.prefix = prefix;
+ }
+
+ @Override
+ public void addRuleInstances(Digester digester) {
+ digester.addObjectCreate(prefix + "action", StrutsAction.class);
+ digester.addSetProperties(prefix + "action");
+ digester.addSetProperties(prefix + "action", "class", "clazz");
+ digester.addSetNext(prefix + "action", "addAction");
+ digester.addObjectCreate(prefix + "action/result", StrutsActionResult.class);
+ digester.addSetProperties(prefix + "action/result");
+ digester.addBeanPropertySetter(prefix + "action/result", "url");
+ digester.addSetNext(prefix + "action/result", "addResult");
+ }
+}
\ No newline at end of file
diff --git a/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/degister/StrutsConfig.java b/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/degister/StrutsConfig.java
new file mode 100644
index 0000000000..b2005c9700
--- /dev/null
+++ b/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/degister/StrutsConfig.java
@@ -0,0 +1,15 @@
+package com.github.eulerlcs.jmr.litestruts.degister;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import lombok.Getter;
+
+public class StrutsConfig {
+ @Getter
+ private Map actionMap = new HashMap<>();
+
+ public void addAction(StrutsAction action) {
+ actionMap.put(action.getName(), action);
+ }
+}
diff --git a/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/degister/StrutsDigester.java b/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/degister/StrutsDigester.java
new file mode 100644
index 0000000000..f466c8cb10
--- /dev/null
+++ b/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/degister/StrutsDigester.java
@@ -0,0 +1,13 @@
+package com.github.eulerlcs.jmr.litestruts.degister;
+
+import org.apache.commons.digester.Digester;
+
+public class StrutsDigester {
+ public static Digester newInstance() {
+ Digester d = new Digester();
+ d.addObjectCreate("struts", StrutsConfig.class);
+ d.addSetProperties("struts");
+ d.addRuleSet(new StrutsActionRulerSet("struts/"));
+ return d;
+ }
+}
diff --git a/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/util/package-info.java b/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/util/package-info.java
deleted file mode 100644
index 6797c45b67..0000000000
--- a/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/main/java/com/github/eulerlcs/jmr/litestruts/util/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- *
- */
-package com.github.eulerlcs.jmr.litestruts.util;
\ No newline at end of file
diff --git a/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/test/java/com/github/eulerlcs/jmr/litestruts/core/StrutsTest.java b/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/test/java/com/github/eulerlcs/jmr/litestruts/core/StrutsTest.java
new file mode 100644
index 0000000000..b2fa989915
--- /dev/null
+++ b/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/test/java/com/github/eulerlcs/jmr/litestruts/core/StrutsTest.java
@@ -0,0 +1,38 @@
+package com.github.eulerlcs.jmr.litestruts.core;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class StrutsTest {
+
+ @Test
+ public void testLoginActionSuccess() {
+
+ String actionName = "login";
+
+ Map params = new HashMap();
+ params.put("name", "test");
+ params.put("password", "1234");
+
+ View view = Struts.runAction(actionName, params);
+
+ Assert.assertEquals("/jsp/homepage.jsp", view.getJsp());
+ Assert.assertEquals("login successful", view.getParameters().get("message"));
+ }
+
+ @Test
+ public void testLoginActionFailed() {
+ String actionName = "login";
+ Map params = new HashMap();
+ params.put("name", "test");
+ params.put("password", "123456"); // 密码和预设的不一致
+
+ View view = Struts.runAction(actionName, params);
+
+ Assert.assertEquals("/jsp/showLogin.jsp", view.getJsp());
+ Assert.assertEquals("login failed,please check your user/pwd", view.getParameters().get("message"));
+ }
+}
diff --git a/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/test/java/com/github/eulerlcs/jmr/litestruts/util/ArrayUtilTest.java b/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/test/java/com/github/eulerlcs/jmr/litestruts/util/ArrayUtilTest.java
index b2957d01b7..5e88599842 100644
--- a/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/test/java/com/github/eulerlcs/jmr/litestruts/util/ArrayUtilTest.java
+++ b/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/src/test/java/com/github/eulerlcs/jmr/litestruts/util/ArrayUtilTest.java
@@ -8,6 +8,8 @@
import org.junit.Test;
+import com.github.eulerlcs.jmr.litestruts.algorithm.ArrayUtil;
+
public class ArrayUtilTest {
@Test
@@ -246,7 +248,7 @@ public void getPrimes_24() {
@Test
public void getPerfectNumbers_max() {
long max = Long.MAX_VALUE;
- max = 100000;
+ max = 10000;
long[] expecteds = { 6, 28, 496, 8128, 33550336, 8589869056L, 137438691328L, 2305843008139952128L };
long[] newArr = ArrayUtil.getPerfectNumbers(max);
diff --git a/group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/data/.gitkeep b/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/data/.gitkeep
similarity index 100%
rename from group09/41689722.eulerlcs/2.code/jmr-61-170305-litestruts/data/.gitkeep
rename to group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/data/.gitkeep
diff --git a/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/pom.xml b/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/pom.xml
new file mode 100644
index 0000000000..8f300f8306
--- /dev/null
+++ b/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/pom.xml
@@ -0,0 +1,39 @@
+
+ 4.0.0
+
+ com.github.eulerlcs
+ jmr-02-parent
+ 0.0.1-SNAPSHOT
+ ../jmr-02-parent/pom.xml
+
+ jmr-61-170312-multiThreadDownload
+ eulerlcs master java road - download file by multiple thread
+
+
+
+ commons-digester
+ commons-digester
+
+
+ org.projectlombok
+ lombok
+
+
+ org.slf4j
+ slf4j-api
+
+
+ org.slf4j
+ slf4j-log4j12
+
+
+ junit
+ junit
+
+
+ com.github.stefanbirkner
+ system-rules
+
+
+
\ No newline at end of file
diff --git a/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/java/com/github/eulerlcs/jmr/multiDL/DownloadThread.java b/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/java/com/github/eulerlcs/jmr/multiDL/DownloadThread.java
new file mode 100644
index 0000000000..b3fb699944
--- /dev/null
+++ b/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/java/com/github/eulerlcs/jmr/multiDL/DownloadThread.java
@@ -0,0 +1,20 @@
+package com.github.eulerlcs.jmr.multiDL;
+
+import com.github.eulerlcs.jmr.multiDL.api.Connection;
+
+public class DownloadThread extends Thread {
+ Connection conn;
+ int startPos;
+ int endPos;
+
+ public DownloadThread(Connection conn, int startPos, int endPos) {
+ this.conn = conn;
+ this.startPos = startPos;
+ this.endPos = endPos;
+ }
+
+ @Override
+ public void run() {
+
+ }
+}
diff --git a/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/java/com/github/eulerlcs/jmr/multiDL/FileDownloader.java b/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/java/com/github/eulerlcs/jmr/multiDL/FileDownloader.java
new file mode 100644
index 0000000000..fca00437d7
--- /dev/null
+++ b/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/java/com/github/eulerlcs/jmr/multiDL/FileDownloader.java
@@ -0,0 +1,64 @@
+package com.github.eulerlcs.jmr.multiDL;
+
+import com.github.eulerlcs.jmr.multiDL.api.Connection;
+import com.github.eulerlcs.jmr.multiDL.api.ConnectionException;
+import com.github.eulerlcs.jmr.multiDL.api.ConnectionManager;
+import com.github.eulerlcs.jmr.multiDL.api.DownloadListener;
+
+public class FileDownloader {
+
+ String url;
+
+ DownloadListener listener;
+
+ ConnectionManager cm;
+
+ public FileDownloader(String _url) {
+ this.url = _url;
+ }
+
+ public void execute() {
+ // 在这里实现你的代码, 注意: 需要用多线程实现下载
+ // 这个类依赖于其他几个接口, 你需要写这几个接口的实现代码
+ // (1) ConnectionManager , 可以打开一个连接,通过Connection可以读取其中的一段(用startPos,
+ // endPos来指定)
+ // (2) DownloadListener, 由于是多线程下载, 调用这个类的客户端不知道什么时候结束,所以你需要实现当所有
+ // 线程都执行完以后, 调用listener的notifiedFinished方法, 这样客户端就能收到通知。
+ // 具体的实现思路:
+ // 1. 需要调用ConnectionManager的open方法打开连接,
+ // 然后通过Connection.getContentLength方法获得文件的长度
+ // 2. 至少启动3个线程下载, 注意每个线程需要先调用ConnectionManager的open方法
+ // 然后调用read方法, read方法中有读取文件的开始位置和结束位置的参数, 返回值是byte[]数组
+ // 3. 把byte数组写入到文件中
+ // 4. 所有的线程都下载完成以后, 需要调用listener的notifiedFinished方法
+
+ // 下面的代码是示例代码, 也就是说只有一个线程, 你需要改造成多线程的。
+ Connection conn = null;
+ try {
+ conn = cm.open(this.url);
+
+ int length = conn.getContentLength();
+
+ new DownloadThread(conn, 0, length - 1).start();
+
+ } catch (ConnectionException e) {
+ e.printStackTrace();
+ } finally {
+ if (conn != null) {
+ conn.close();
+ }
+ }
+ }
+
+ public void setListener(DownloadListener listener) {
+ this.listener = listener;
+ }
+
+ public void setConnectionManager(ConnectionManager ucm) {
+ this.cm = ucm;
+ }
+
+ public DownloadListener getListener() {
+ return this.listener;
+ }
+}
diff --git a/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/java/com/github/eulerlcs/jmr/multiDL/algorithm/Iterator.java b/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/java/com/github/eulerlcs/jmr/multiDL/algorithm/Iterator.java
new file mode 100644
index 0000000000..2d937d0c53
--- /dev/null
+++ b/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/java/com/github/eulerlcs/jmr/multiDL/algorithm/Iterator.java
@@ -0,0 +1,7 @@
+package com.github.eulerlcs.jmr.multiDL.algorithm;
+
+public interface Iterator {
+ public boolean hasNext();
+ public Object next();
+
+}
diff --git a/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/java/com/github/eulerlcs/jmr/multiDL/algorithm/LinkedList.java b/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/java/com/github/eulerlcs/jmr/multiDL/algorithm/LinkedList.java
new file mode 100644
index 0000000000..fdae519c0a
--- /dev/null
+++ b/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/java/com/github/eulerlcs/jmr/multiDL/algorithm/LinkedList.java
@@ -0,0 +1,122 @@
+package com.github.eulerlcs.jmr.multiDL.algorithm;
+
+public class LinkedList implements List {
+
+ private Node head;
+
+ public void add(Object o){
+
+ }
+ public void add(int index , Object o){
+
+ }
+ public Object get(int index){
+ return null;
+ }
+ public Object remove(int index){
+ return null;
+ }
+
+ public int size(){
+ return -1;
+ }
+
+ public void addFirst(Object o){
+
+ }
+ public void addLast(Object o){
+
+ }
+ public Object removeFirst(){
+ return null;
+ }
+ public Object removeLast(){
+ return null;
+ }
+ public Iterator iterator(){
+ return null;
+ }
+
+
+ private static class Node{
+ Object data;
+ Node next;
+
+ }
+
+ /**
+ * 把该链表逆置
+ * 例如链表为 3->7->10 , 逆置后变为 10->7->3
+ */
+ public void reverse(){
+
+ }
+
+ /**
+ * 删除一个单链表的前半部分
+ * 例如:list = 2->5->7->8 , 删除以后的值为 7->8
+ * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10
+
+ */
+ public void removeFirstHalf(){
+
+ }
+
+ /**
+ * 从第i个元素开始, 删除length 个元素 , 注意i从0开始
+ * @param i
+ * @param length
+ */
+ public void remove(int i, int length){
+
+ }
+ /**
+ * 假定当前链表和list均包含已升序排列的整数
+ * 从当前链表中取出那些list所指定的元素
+ * 例如当前链表 = 11->101->201->301->401->501->601->701
+ * listB = 1->3->4->6
+ * 返回的结果应该是[101,301,401,601]
+ * @param list
+ */
+ public static int[] getElements(LinkedList list){
+ return null;
+ }
+
+ /**
+ * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。
+ * 从当前链表中中删除在list中出现的元素
+
+ * @param list
+ */
+
+ public void subtract(LinkedList list){
+
+ }
+
+ /**
+ * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。
+ * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同)
+ */
+ public void removeDuplicateValues(){
+
+ }
+
+ /**
+ * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。
+ * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素)
+ * @param min
+ * @param max
+ */
+ public void removeRange(int min, int max){
+
+ }
+
+ /**
+ * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同)
+ * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列
+ * @param list
+ */
+ public LinkedList intersection( LinkedList list){
+ return null;
+ }
+}
diff --git a/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/java/com/github/eulerlcs/jmr/multiDL/algorithm/List.java b/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/java/com/github/eulerlcs/jmr/multiDL/algorithm/List.java
new file mode 100644
index 0000000000..ad07c355b4
--- /dev/null
+++ b/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/java/com/github/eulerlcs/jmr/multiDL/algorithm/List.java
@@ -0,0 +1,9 @@
+package com.github.eulerlcs.jmr.multiDL.algorithm;
+
+public interface List {
+ public void add(Object o);
+ public void add(int index, Object o);
+ public Object get(int index);
+ public Object remove(int index);
+ public int size();
+}
diff --git a/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/java/com/github/eulerlcs/jmr/multiDL/api/Connection.java b/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/java/com/github/eulerlcs/jmr/multiDL/api/Connection.java
new file mode 100644
index 0000000000..d0037a877b
--- /dev/null
+++ b/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/java/com/github/eulerlcs/jmr/multiDL/api/Connection.java
@@ -0,0 +1,28 @@
+package com.github.eulerlcs.jmr.multiDL.api;
+
+import java.io.IOException;
+
+public interface Connection {
+ /**
+ * 给定开始和结束位置, 读取数据, 返回值是字节数组
+ *
+ * @param startPos
+ * 开始位置, 从0开始
+ * @param endPos
+ * 结束位置
+ * @return
+ */
+ public byte[] read(int startPos, int endPos) throws IOException;
+
+ /**
+ * 得到数据内容的长度
+ *
+ * @return
+ */
+ public int getContentLength();
+
+ /**
+ * 关闭连接
+ */
+ public void close();
+}
diff --git a/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/java/com/github/eulerlcs/jmr/multiDL/api/ConnectionException.java b/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/java/com/github/eulerlcs/jmr/multiDL/api/ConnectionException.java
new file mode 100644
index 0000000000..92bf290f8e
--- /dev/null
+++ b/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/java/com/github/eulerlcs/jmr/multiDL/api/ConnectionException.java
@@ -0,0 +1,5 @@
+package com.github.eulerlcs.jmr.multiDL.api;
+
+public class ConnectionException extends Exception {
+ private static final long serialVersionUID = 1L;
+}
diff --git a/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/java/com/github/eulerlcs/jmr/multiDL/api/ConnectionManager.java b/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/java/com/github/eulerlcs/jmr/multiDL/api/ConnectionManager.java
new file mode 100644
index 0000000000..a350054dd4
--- /dev/null
+++ b/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/java/com/github/eulerlcs/jmr/multiDL/api/ConnectionManager.java
@@ -0,0 +1,11 @@
+package com.github.eulerlcs.jmr.multiDL.api;
+
+public interface ConnectionManager {
+ /**
+ * 给定一个url , 打开一个连接
+ *
+ * @param url
+ * @return
+ */
+ public Connection open(String url) throws ConnectionException;
+}
diff --git a/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/java/com/github/eulerlcs/jmr/multiDL/api/DownloadListener.java b/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/java/com/github/eulerlcs/jmr/multiDL/api/DownloadListener.java
new file mode 100644
index 0000000000..a2dc179298
--- /dev/null
+++ b/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/java/com/github/eulerlcs/jmr/multiDL/api/DownloadListener.java
@@ -0,0 +1,5 @@
+package com.github.eulerlcs.jmr.multiDL.api;
+
+public interface DownloadListener {
+ public void notifyFinished();
+}
diff --git a/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/java/com/github/eulerlcs/jmr/multiDL/impl/ConnectionImpl.java b/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/java/com/github/eulerlcs/jmr/multiDL/impl/ConnectionImpl.java
new file mode 100644
index 0000000000..613c692750
--- /dev/null
+++ b/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/java/com/github/eulerlcs/jmr/multiDL/impl/ConnectionImpl.java
@@ -0,0 +1,25 @@
+package com.github.eulerlcs.jmr.multiDL.impl;
+
+import java.io.IOException;
+
+import com.github.eulerlcs.jmr.multiDL.api.Connection;
+
+public class ConnectionImpl implements Connection {
+
+ @Override
+ public byte[] read(int startPos, int endPos) throws IOException {
+
+ return null;
+ }
+
+ @Override
+ public int getContentLength() {
+
+ return 0;
+ }
+
+ @Override
+ public void close() {
+
+ }
+}
diff --git a/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/java/com/github/eulerlcs/jmr/multiDL/impl/ConnectionManagerImpl.java b/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/java/com/github/eulerlcs/jmr/multiDL/impl/ConnectionManagerImpl.java
new file mode 100644
index 0000000000..d50036b8c8
--- /dev/null
+++ b/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/java/com/github/eulerlcs/jmr/multiDL/impl/ConnectionManagerImpl.java
@@ -0,0 +1,14 @@
+package com.github.eulerlcs.jmr.multiDL.impl;
+
+import com.github.eulerlcs.jmr.multiDL.api.Connection;
+import com.github.eulerlcs.jmr.multiDL.api.ConnectionException;
+import com.github.eulerlcs.jmr.multiDL.api.ConnectionManager;
+
+public class ConnectionManagerImpl implements ConnectionManager {
+
+ @Override
+ public Connection open(String url) throws ConnectionException {
+
+ return null;
+ }
+}
diff --git a/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/resources/log4j.xml b/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/resources/log4j.xml
new file mode 100644
index 0000000000..831b8d9ce3
--- /dev/null
+++ b/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/main/resources/log4j.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/test/java/com/github/eulerlcs/jmr/multiDL/FileDownloaderTest.java b/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/test/java/com/github/eulerlcs/jmr/multiDL/FileDownloaderTest.java
new file mode 100644
index 0000000000..cfb3274124
--- /dev/null
+++ b/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/test/java/com/github/eulerlcs/jmr/multiDL/FileDownloaderTest.java
@@ -0,0 +1,53 @@
+package com.github.eulerlcs.jmr.multiDL;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.github.eulerlcs.jmr.multiDL.api.ConnectionManager;
+import com.github.eulerlcs.jmr.multiDL.api.DownloadListener;
+import com.github.eulerlcs.jmr.multiDL.impl.ConnectionManagerImpl;
+
+public class FileDownloaderTest {
+ boolean downloadFinished = false;
+
+ @Before
+ public void setUp() throws Exception {
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ @Test
+ public void testDownload() {
+ String url = "http://localhost:8080/test.jpg";
+
+ FileDownloader downloader = new FileDownloader(url);
+
+ ConnectionManager cm = new ConnectionManagerImpl();
+ downloader.setConnectionManager(cm);
+
+ downloader.setListener(new DownloadListener() {
+ @Override
+ public void notifyFinished() {
+ downloadFinished = true;
+ }
+ });
+
+ downloader.execute();
+
+ // 等待多线程下载程序执行完毕
+ while (!downloadFinished) {
+ try {
+ System.out.println("还没有下载完成,休眠五秒");
+ // 休眠5秒
+ Thread.sleep(5000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ System.out.println("下载完成!");
+ }
+}
diff --git a/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/test/resources/.gitkeep b/group09/41689722.eulerlcs/2.code/jmr-61-170312-multiThreadDownload/src/test/resources/.gitkeep
new file mode 100644
index 0000000000..e69de29bb2