diff --git a/mail-api/pom.xml b/mail-api/pom.xml
new file mode 100644
index 0000000..c7ab58f
--- /dev/null
+++ b/mail-api/pom.xml
@@ -0,0 +1,26 @@
+
+
+ 4.0.0
+
+
+ ru.javaops
+ parent
+ ../parent/pom.xml
+ 1.0-SNAPSHOT
+
+
+ mail-api
+ 1.0-SNAPSHOT
+ jar
+ mail-api
+
+
+
+ ru.javaops
+ common
+ ${project.version}
+
+
+
\ No newline at end of file
diff --git a/src/main/java/ru/javaops/masterjava/service/MailService.java b/mail-api/src/main/java/ru/javaops/masterjava/MailService.java
similarity index 99%
rename from src/main/java/ru/javaops/masterjava/service/MailService.java
rename to mail-api/src/main/java/ru/javaops/masterjava/MailService.java
index b5ec9f2..5c469f4 100644
--- a/src/main/java/ru/javaops/masterjava/service/MailService.java
+++ b/mail-api/src/main/java/ru/javaops/masterjava/MailService.java
@@ -1,4 +1,4 @@
-package ru.javaops.masterjava.service;
+package ru.javaops.masterjava;
import java.util.ArrayList;
import java.util.List;
diff --git a/mail-service/pom.xml b/mail-service/pom.xml
new file mode 100644
index 0000000..02e245a
--- /dev/null
+++ b/mail-service/pom.xml
@@ -0,0 +1,27 @@
+
+
+ 4.0.0
+
+
+ ru.javaops
+ parent-war
+ ../parent-war/pom.xml
+ 2.0-SNAPSHOT
+
+
+ mail-service
+ 1.0-SNAPSHOT
+ war
+ Mail service
+
+
+
+
+ ru.javaops
+ mail-api
+ 1.0-SNAPSHOT
+
+
+
\ No newline at end of file
diff --git a/parent-war/pom.xml b/parent-war/pom.xml
new file mode 100644
index 0000000..ab46dba
--- /dev/null
+++ b/parent-war/pom.xml
@@ -0,0 +1,32 @@
+
+
+ 4.0.0
+
+
+ ru.javaops
+ parent
+ ../parent/pom.xml
+ 1.0-SNAPSHOT
+
+
+ parent-war
+ pom
+ 2.0-SNAPSHOT
+ Parent war
+
+
+ install
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.2.0
+
+ false
+
+
+
+
+
\ No newline at end of file
diff --git a/parent/pom.xml b/parent/pom.xml
index d7b056d..4a6019e 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -11,7 +11,7 @@
Parent
- 1.8
+ 17
UTF-8
UTF-8
@@ -45,11 +45,6 @@
guava
23.3-jre
-
- one.util
- streamex
- RELEASE
-
diff --git a/pom.xml b/pom.xml
index 0085819..5c0fe63 100644
--- a/pom.xml
+++ b/pom.xml
@@ -14,11 +14,9 @@
upload
common
-
diff --git a/src/test/java/ru/javaops/masterjava/MainXml.java b/src/test/java/ru/javaops/masterjava/MainXml.java
deleted file mode 100644
index 8f57825..0000000
--- a/src/test/java/ru/javaops/masterjava/MainXml.java
+++ /dev/null
@@ -1,140 +0,0 @@
-package ru.javaops.masterjava;
-
-import com.google.common.base.Splitter;
-import com.google.common.io.Resources;
-import j2html.tags.ContainerTag;
-import one.util.streamex.StreamEx;
-import ru.javaops.masterjava.xml.schema.ObjectFactory;
-import ru.javaops.masterjava.xml.schema.Payload;
-import ru.javaops.masterjava.xml.schema.Project;
-import ru.javaops.masterjava.xml.schema.User;
-import ru.javaops.masterjava.xml.util.JaxbParser;
-import ru.javaops.masterjava.xml.util.Schemas;
-import ru.javaops.masterjava.xml.util.StaxStreamProcessor;
-import ru.javaops.masterjava.xml.util.XsltProcessor;
-
-import javax.xml.stream.events.XMLEvent;
-import java.io.InputStream;
-import java.io.Writer;
-import java.net.URL;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import java.util.*;
-import java.util.stream.Collectors;
-
-import static com.google.common.base.Strings.nullToEmpty;
-import static j2html.TagCreator.*;
-
-public class MainXml {
-
- private static final Comparator USER_COMPARATOR = Comparator.comparing(User::getValue).thenComparing(User::getEmail);
-
- public static void main(String[] args) throws Exception {
- if (args.length != 1) {
- System.out.println("Required argument: projectName");
- System.exit(1);
- }
- String projectName = args[0];
- URL payloadUrl = Resources.getResource("payload.xml");
-
- Set users = parseByJaxb(projectName, payloadUrl);
- users.forEach(System.out::println);
-
- System.out.println();
- String html = toHtml(users, projectName);
- System.out.println(html);
- try (Writer writer = Files.newBufferedWriter(Paths.get("out/users.html"))) {
- writer.write(html);
- }
-
- System.out.println();
- users = processByStax(projectName, payloadUrl);
- users.forEach(System.out::println);
-
- System.out.println();
- html = transform(projectName, payloadUrl);
- try (Writer writer = Files.newBufferedWriter(Paths.get("out/groups.html"))) {
- writer.write(html);
- }
- }
-
- private static Set parseByJaxb(String projectName, URL payloadUrl) throws Exception {
- JaxbParser parser = new JaxbParser(ObjectFactory.class);
- parser.setSchema(Schemas.ofClasspath("payload.xsd"));
- Payload payload;
- try (InputStream is = payloadUrl.openStream()) {
- payload = parser.unmarshal(is);
- }
-
- Project project = StreamEx.of(payload.getProjects().getProject())
- .filter(p -> p.getName().equals(projectName))
- .findAny()
- .orElseThrow(() -> new IllegalArgumentException("Invalid project name '" + projectName + '\''));
-
- final Set groups = new HashSet<>(project.getGroup()); // identity compare
- return StreamEx.of(payload.getUsers().getUser())
- .filter(u -> !Collections.disjoint(groups, u.getGroupRefs()))
- .collect(
- Collectors.toCollection(() -> new TreeSet<>(USER_COMPARATOR))
- );
- }
-
- private static Set processByStax(String projectName, URL payloadUrl) throws Exception {
-
- try (InputStream is = payloadUrl.openStream()) {
- StaxStreamProcessor processor = new StaxStreamProcessor(is);
- final Set groupNames = new HashSet<>();
-
- // Projects loop
- projects:
- while (processor.startElement("Project", "Projects")) {
- if (projectName.equals(processor.getAttribute("name"))) {
- while (processor.startElement("Group", "Project")) {
- groupNames.add(processor.getAttribute("name"));
- }
- break;
- }
- }
- if (groupNames.isEmpty()) {
- throw new IllegalArgumentException("Invalid " + projectName + " or no groups");
- }
-
- // Users loop
- Set users = new TreeSet<>(USER_COMPARATOR);
-
- JaxbParser parser = new JaxbParser(User.class);
- while (processor.doUntil(XMLEvent.START_ELEMENT, "User")) {
- String groupRefs = processor.getAttribute("groupRefs");
- if (!Collections.disjoint(groupNames, Splitter.on(' ').splitToList(nullToEmpty(groupRefs)))) {
- User user = parser.unmarshal(processor.getReader(), User.class);
- users.add(user);
- }
- }
- return users;
- }
- }
-
- private static String toHtml(Set users, String projectName) {
- final ContainerTag table = table().with(
- tr().with(th("FullName"), th("email")))
- .attr("border", "1")
- .attr("cellpadding", "8")
- .attr("cellspacing", "0");
-
- users.forEach(u -> table.with(tr().with(td(u.getValue()), td(u.getEmail()))));
-
- return html().with(
- head().with(title(projectName + " users")),
- body().with(h1(projectName + " users"), table)
- ).render();
- }
-
- private static String transform(String projectName, URL payloadUrl) throws Exception {
- URL xsl = Resources.getResource("groups.xsl");
- try (InputStream xmlStream = payloadUrl.openStream(); InputStream xslStream = xsl.openStream()) {
- XsltProcessor processor = new XsltProcessor(xslStream);
- processor.setParameter("projectName", projectName);
- return processor.transform(xmlStream);
- }
- }
-}
diff --git a/src/test/java/ru/javaops/masterjava/xml/util/JaxbParserTest.java b/src/test/java/ru/javaops/masterjava/xml/util/JaxbParserTest.java
deleted file mode 100644
index 6232654..0000000
--- a/src/test/java/ru/javaops/masterjava/xml/util/JaxbParserTest.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package ru.javaops.masterjava.xml.util;
-
-import com.google.common.io.Resources;
-import org.junit.Test;
-import ru.javaops.masterjava.xml.schema.CityType;
-import ru.javaops.masterjava.xml.schema.ObjectFactory;
-import ru.javaops.masterjava.xml.schema.Payload;
-
-import javax.xml.bind.JAXBElement;
-import javax.xml.namespace.QName;
-
-public class JaxbParserTest {
- private static final JaxbParser JAXB_PARSER = new JaxbParser(ObjectFactory.class);
-
- static {
- JAXB_PARSER.setSchema(Schemas.ofClasspath("payload.xsd"));
- }
-
- @Test
- public void testPayload() throws Exception {
-// JaxbParserTest.class.getResourceAsStream("/city.xml")
- Payload payload = JAXB_PARSER.unmarshal(
- Resources.getResource("payload.xml").openStream());
- String strPayload = JAXB_PARSER.marshal(payload);
- JAXB_PARSER.validate(strPayload);
- System.out.println(strPayload);
- }
-
- @Test
- public void testCity() throws Exception {
- JAXBElement cityElement = JAXB_PARSER.unmarshal(
- Resources.getResource("city.xml").openStream());
- CityType city = cityElement.getValue();
- JAXBElement cityElement2 =
- new JAXBElement<>(new QName("http://javaops.ru", "City"), CityType.class, city);
- String strCity = JAXB_PARSER.marshal(cityElement2);
- JAXB_PARSER.validate(strCity);
- System.out.println(strCity);
- }
-}
\ No newline at end of file
diff --git a/src/test/java/ru/javaops/masterjava/xml/util/StaxStreamProcessorTest.java b/src/test/java/ru/javaops/masterjava/xml/util/StaxStreamProcessorTest.java
deleted file mode 100644
index fd55963..0000000
--- a/src/test/java/ru/javaops/masterjava/xml/util/StaxStreamProcessorTest.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package ru.javaops.masterjava.xml.util;
-
-import com.google.common.io.Resources;
-import org.junit.Test;
-
-import javax.xml.stream.XMLStreamReader;
-import javax.xml.stream.events.XMLEvent;
-
-public class StaxStreamProcessorTest {
- @Test
- public void readCities() throws Exception {
- try (StaxStreamProcessor processor =
- new StaxStreamProcessor(Resources.getResource("payload.xml").openStream())) {
- XMLStreamReader reader = processor.getReader();
- while (reader.hasNext()) {
- int event = reader.next();
- if (event == XMLEvent.START_ELEMENT) {
- if ("City".equals(reader.getLocalName())) {
- System.out.println(reader.getElementText());
- }
- }
- }
- }
- }
-
- @Test
- public void readCities2() throws Exception {
- try (StaxStreamProcessor processor =
- new StaxStreamProcessor(Resources.getResource("payload.xml").openStream())) {
- String city;
- while ((city = processor.getElementValue("City")) != null) {
- System.out.println(city);
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/test/java/ru/javaops/masterjava/xml/util/XPathProcessorTest.java b/src/test/java/ru/javaops/masterjava/xml/util/XPathProcessorTest.java
deleted file mode 100644
index 199f676..0000000
--- a/src/test/java/ru/javaops/masterjava/xml/util/XPathProcessorTest.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package ru.javaops.masterjava.xml.util;
-
-import com.google.common.io.Resources;
-import org.junit.Test;
-import org.w3c.dom.NodeList;
-
-import javax.xml.xpath.XPathConstants;
-import javax.xml.xpath.XPathExpression;
-import java.io.InputStream;
-import java.util.stream.IntStream;
-
-public class XPathProcessorTest {
- @Test
- public void getCities() throws Exception {
- try (InputStream is =
- Resources.getResource("payload.xml").openStream()) {
- XPathProcessor processor = new XPathProcessor(is);
- XPathExpression expression =
- XPathProcessor.getExpression("/*[name()='Payload']/*[name()='Cities']/*[name()='City']/text()");
- NodeList nodes = processor.evaluate(expression, XPathConstants.NODESET);
- IntStream.range(0, nodes.getLength()).forEach(
- i -> System.out.println(nodes.item(i).getNodeValue())
- );
- }
- }
-}
\ No newline at end of file
diff --git a/src/test/java/ru/javaops/masterjava/xml/util/XsltProcessorTest.java b/src/test/java/ru/javaops/masterjava/xml/util/XsltProcessorTest.java
deleted file mode 100644
index d7f42a6..0000000
--- a/src/test/java/ru/javaops/masterjava/xml/util/XsltProcessorTest.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package ru.javaops.masterjava.xml.util;
-
-import com.google.common.io.Resources;
-import org.junit.Test;
-
-import java.io.InputStream;
-
-public class XsltProcessorTest {
- @Test
- public void transform() throws Exception {
- try (InputStream xslInputStream = Resources.getResource("cities.xsl").openStream();
- InputStream xmlInputStream = Resources.getResource("payload.xml").openStream()) {
-
- XsltProcessor processor = new XsltProcessor(xslInputStream);
- System.out.println(processor.transform(xmlInputStream));
- }
- }
-}
diff --git a/test/pom.xml b/test/pom.xml
new file mode 100644
index 0000000..e0bbf07
--- /dev/null
+++ b/test/pom.xml
@@ -0,0 +1,26 @@
+
+
+ 4.0.0
+
+
+ ru.javaops
+ parent
+ ../parent/pom.xml
+ 1.0-SNAPSHOT
+
+
+ test
+ 1.0-SNAPSHOT
+ jar
+ Test
+
+
+
+ org.openjdk.jmh
+ jmh-core
+ 1.36
+
+
+
\ No newline at end of file
diff --git a/src/main/java/ru/javaops/masterjava/matrix/MainMatrix.java b/test/src/main/java/ru/javaops/mastrejava/matrix/MainMatrix.java
similarity index 98%
rename from src/main/java/ru/javaops/masterjava/matrix/MainMatrix.java
rename to test/src/main/java/ru/javaops/mastrejava/matrix/MainMatrix.java
index 1f13806..1ac8b28 100644
--- a/src/main/java/ru/javaops/masterjava/matrix/MainMatrix.java
+++ b/test/src/main/java/ru/javaops/mastrejava/matrix/MainMatrix.java
@@ -1,4 +1,4 @@
-package ru.javaops.masterjava.matrix;
+package ru.javaops.mastrejava.matrix;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
diff --git a/src/main/java/ru/javaops/masterjava/matrix/MatrixBenchmark.java b/test/src/main/java/ru/javaops/mastrejava/matrix/MatrixBenchmark.java
similarity index 98%
rename from src/main/java/ru/javaops/masterjava/matrix/MatrixBenchmark.java
rename to test/src/main/java/ru/javaops/mastrejava/matrix/MatrixBenchmark.java
index 2df2fc6..014180d 100644
--- a/src/main/java/ru/javaops/masterjava/matrix/MatrixBenchmark.java
+++ b/test/src/main/java/ru/javaops/mastrejava/matrix/MatrixBenchmark.java
@@ -1,4 +1,4 @@
-package ru.javaops.masterjava.matrix;
+package ru.javaops.mastrejava.matrix;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
diff --git a/src/main/java/ru/javaops/masterjava/matrix/MatrixUtil.java b/test/src/main/java/ru/javaops/mastrejava/matrix/MatrixUtil.java
similarity index 99%
rename from src/main/java/ru/javaops/masterjava/matrix/MatrixUtil.java
rename to test/src/main/java/ru/javaops/mastrejava/matrix/MatrixUtil.java
index d00a67a..bd4d4f6 100644
--- a/src/main/java/ru/javaops/masterjava/matrix/MatrixUtil.java
+++ b/test/src/main/java/ru/javaops/mastrejava/matrix/MatrixUtil.java
@@ -1,4 +1,4 @@
-package ru.javaops.masterjava.matrix;
+package ru.javaops.mastrejava.matrix;
import java.util.ArrayList;
import java.util.List;
diff --git a/upload/pom.xml b/upload/pom.xml
index 7cac01c..860512e 100644
--- a/upload/pom.xml
+++ b/upload/pom.xml
@@ -6,9 +6,9 @@
ru.javaops
- parent
- ../parent/pom.xml
- 1.0-SNAPSHOT
+ 2.0-SNAPSHOT
+ parent-war
+ ../parent-war/pom.xml
upload
@@ -16,18 +16,6 @@
war
Upload
-
-
-
- org.apache.maven.plugins
- maven-war-plugin
- 3.2.0
-
- false
-
-
-
-
@@ -35,5 +23,28 @@
common
${project.version}
+
+ commons-fileupload
+ commons-fileupload
+ 1.5
+
+
+ org.glassfish
+ javax.xml.bind
+ 10.0-b28
+
+
+
+ javax.servlet
+ javax.servlet-api
+ 4.0.1
+ provided
+
+
+ org.thymeleaf
+ thymeleaf
+ 3.0.2.RELEASE
+
+
\ No newline at end of file
diff --git a/upload/src/main/java/ru/javaops/masterjava/xml/export/ExportXmlServlet.java b/upload/src/main/java/ru/javaops/masterjava/xml/export/ExportXmlServlet.java
new file mode 100644
index 0000000..bfbd4f3
--- /dev/null
+++ b/upload/src/main/java/ru/javaops/masterjava/xml/export/ExportXmlServlet.java
@@ -0,0 +1,62 @@
+package ru.javaops.masterjava.xml.export;
+
+
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.FileItemIterator;
+import org.apache.commons.fileupload.FileItemStream;
+import org.apache.commons.fileupload.FileUploadException;
+import org.apache.commons.fileupload.disk.DiskFileItemFactory;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+import org.thymeleaf.TemplateEngine;
+import org.thymeleaf.context.WebContext;
+import ru.javaops.masterjava.xml.model.User;
+import ru.javaops.masterjava.xml.util.ThymeleafUtil;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.stream.XMLStreamException;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+@WebServlet(name = "ExportXml", urlPatterns = "/upload")
+public class ExportXmlServlet extends HttpServlet {
+ private final UserExport userExport = new UserExport();
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ final WebContext webContext = new WebContext(req, resp, req.getServletContext(), req.getLocale());
+ final TemplateEngine templateEngine = ThymeleafUtil.getTemplateEngine(req.getServletContext());
+ templateEngine.process("export", webContext, resp.getWriter());
+ }
+
+ @Override
+ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ final ServletFileUpload servletFileUpload = new ServletFileUpload();
+ final WebContext webContext = new WebContext(req, resp, req.getServletContext(), req.getLocale());
+ final TemplateEngine templateEngine = ThymeleafUtil.getTemplateEngine(req.getServletContext());
+
+ try {
+ final FileItemIterator itemIterator = servletFileUpload.getItemIterator(req);
+ while (itemIterator.hasNext()) {
+ FileItemStream fileItemStream = itemIterator.next();
+ if (!fileItemStream.isFormField()) {
+ try (InputStream is = fileItemStream.openStream()) {
+ List users = userExport.process(is);
+ webContext.setVariable("users", users);
+ templateEngine.process("result", webContext, resp.getWriter());
+ }
+ }
+ }
+
+ } catch (Exception e) {
+ webContext.setVariable("exception", e);
+ templateEngine.process("exception", webContext, resp.getWriter());
+ }
+ }
+}
diff --git a/upload/src/main/java/ru/javaops/masterjava/xml/export/UserExport.java b/upload/src/main/java/ru/javaops/masterjava/xml/export/UserExport.java
new file mode 100644
index 0000000..718d2fb
--- /dev/null
+++ b/upload/src/main/java/ru/javaops/masterjava/xml/export/UserExport.java
@@ -0,0 +1,27 @@
+package ru.javaops.masterjava.xml.export;
+
+import ru.javaops.masterjava.xml.model.User;
+import ru.javaops.masterjava.xml.model.UserFlag;
+import ru.javaops.masterjava.xml.util.StaxStreamProcessor;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.XMLEvent;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+public class UserExport {
+ public List process(final InputStream in) throws XMLStreamException {
+ final StaxStreamProcessor processor = new StaxStreamProcessor(in);
+ List users = new ArrayList<>();
+
+ while (processor.doUntil(XMLEvent.START_ELEMENT, "User")) {
+ final String email = processor.getAttribute("email");
+ final UserFlag flag = UserFlag.valueOf(processor.getAttribute("flag"));
+ final String fullName = processor.getReader().getElementText();
+ User user = new User(fullName, email, flag);
+ users.add(user);
+ }
+ return users;
+ }
+}
diff --git a/upload/src/main/java/ru/javaops/masterjava/xml/model/User.java b/upload/src/main/java/ru/javaops/masterjava/xml/model/User.java
new file mode 100644
index 0000000..b5c7358
--- /dev/null
+++ b/upload/src/main/java/ru/javaops/masterjava/xml/model/User.java
@@ -0,0 +1,51 @@
+package ru.javaops.masterjava.xml.model;
+
+import java.util.Objects;
+
+public class User {
+ private final Integer id;
+ private final String fullName;
+ private final String email;
+ private final UserFlag flag;
+
+
+ public User(String fullName, String email, UserFlag flag) {
+ this(null, fullName, email, flag);
+ }
+
+ public User(Integer id, String fullName, String email, UserFlag flag) {
+ this.id = id;
+ this.fullName = fullName;
+ this.email = email;
+ this.flag = flag;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public String getFullName() {
+ return fullName;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public UserFlag getFlag() {
+ return flag;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof User)) return false;
+ User user = (User) o;
+ return getId().equals(user.getId()) && getFullName().equals(user.getFullName()) && getEmail().equals(user.getEmail()) && getFlag() == user.getFlag();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(getId(), getFullName(), getEmail(), getFlag());
+ }
+}
diff --git a/upload/src/main/java/ru/javaops/masterjava/xml/model/UserFlag.java b/upload/src/main/java/ru/javaops/masterjava/xml/model/UserFlag.java
new file mode 100644
index 0000000..b41dfd0
--- /dev/null
+++ b/upload/src/main/java/ru/javaops/masterjava/xml/model/UserFlag.java
@@ -0,0 +1,7 @@
+package ru.javaops.masterjava.xml.model;
+
+public enum UserFlag {
+ active,
+ deleted,
+ superuser
+}
diff --git a/src/main/java/ru/javaops/masterjava/xml/schema/CityType.java b/upload/src/main/java/ru/javaops/masterjava/xml/schema/CityType.java
similarity index 100%
rename from src/main/java/ru/javaops/masterjava/xml/schema/CityType.java
rename to upload/src/main/java/ru/javaops/masterjava/xml/schema/CityType.java
diff --git a/src/main/java/ru/javaops/masterjava/xml/schema/FlagType.java b/upload/src/main/java/ru/javaops/masterjava/xml/schema/FlagType.java
similarity index 100%
rename from src/main/java/ru/javaops/masterjava/xml/schema/FlagType.java
rename to upload/src/main/java/ru/javaops/masterjava/xml/schema/FlagType.java
diff --git a/src/main/java/ru/javaops/masterjava/xml/schema/GroupType.java b/upload/src/main/java/ru/javaops/masterjava/xml/schema/GroupType.java
similarity index 100%
rename from src/main/java/ru/javaops/masterjava/xml/schema/GroupType.java
rename to upload/src/main/java/ru/javaops/masterjava/xml/schema/GroupType.java
diff --git a/src/main/java/ru/javaops/masterjava/xml/schema/ObjectFactory.java b/upload/src/main/java/ru/javaops/masterjava/xml/schema/ObjectFactory.java
similarity index 100%
rename from src/main/java/ru/javaops/masterjava/xml/schema/ObjectFactory.java
rename to upload/src/main/java/ru/javaops/masterjava/xml/schema/ObjectFactory.java
diff --git a/src/main/java/ru/javaops/masterjava/xml/schema/Payload.java b/upload/src/main/java/ru/javaops/masterjava/xml/schema/Payload.java
similarity index 100%
rename from src/main/java/ru/javaops/masterjava/xml/schema/Payload.java
rename to upload/src/main/java/ru/javaops/masterjava/xml/schema/Payload.java
diff --git a/src/main/java/ru/javaops/masterjava/xml/schema/Project.java b/upload/src/main/java/ru/javaops/masterjava/xml/schema/Project.java
similarity index 100%
rename from src/main/java/ru/javaops/masterjava/xml/schema/Project.java
rename to upload/src/main/java/ru/javaops/masterjava/xml/schema/Project.java
diff --git a/src/main/java/ru/javaops/masterjava/xml/schema/User.java b/upload/src/main/java/ru/javaops/masterjava/xml/schema/User.java
similarity index 100%
rename from src/main/java/ru/javaops/masterjava/xml/schema/User.java
rename to upload/src/main/java/ru/javaops/masterjava/xml/schema/User.java
diff --git a/src/main/java/ru/javaops/masterjava/xml/util/JaxbMarshaller.java b/upload/src/main/java/ru/javaops/masterjava/xml/util/JaxbMarshaller.java
similarity index 100%
rename from src/main/java/ru/javaops/masterjava/xml/util/JaxbMarshaller.java
rename to upload/src/main/java/ru/javaops/masterjava/xml/util/JaxbMarshaller.java
diff --git a/src/main/java/ru/javaops/masterjava/xml/util/JaxbParser.java b/upload/src/main/java/ru/javaops/masterjava/xml/util/JaxbParser.java
similarity index 100%
rename from src/main/java/ru/javaops/masterjava/xml/util/JaxbParser.java
rename to upload/src/main/java/ru/javaops/masterjava/xml/util/JaxbParser.java
diff --git a/src/main/java/ru/javaops/masterjava/xml/util/JaxbUnmarshaller.java b/upload/src/main/java/ru/javaops/masterjava/xml/util/JaxbUnmarshaller.java
similarity index 100%
rename from src/main/java/ru/javaops/masterjava/xml/util/JaxbUnmarshaller.java
rename to upload/src/main/java/ru/javaops/masterjava/xml/util/JaxbUnmarshaller.java
diff --git a/src/main/java/ru/javaops/masterjava/xml/util/Schemas.java b/upload/src/main/java/ru/javaops/masterjava/xml/util/Schemas.java
similarity index 100%
rename from src/main/java/ru/javaops/masterjava/xml/util/Schemas.java
rename to upload/src/main/java/ru/javaops/masterjava/xml/util/Schemas.java
diff --git a/src/main/java/ru/javaops/masterjava/xml/util/StaxStreamProcessor.java b/upload/src/main/java/ru/javaops/masterjava/xml/util/StaxStreamProcessor.java
similarity index 100%
rename from src/main/java/ru/javaops/masterjava/xml/util/StaxStreamProcessor.java
rename to upload/src/main/java/ru/javaops/masterjava/xml/util/StaxStreamProcessor.java
diff --git a/upload/src/main/java/ru/javaops/masterjava/xml/util/ThymeleafUtil.java b/upload/src/main/java/ru/javaops/masterjava/xml/util/ThymeleafUtil.java
new file mode 100644
index 0000000..3818766
--- /dev/null
+++ b/upload/src/main/java/ru/javaops/masterjava/xml/util/ThymeleafUtil.java
@@ -0,0 +1,35 @@
+package ru.javaops.masterjava.xml.util;
+
+import org.thymeleaf.TemplateEngine;
+import org.thymeleaf.templatemode.TemplateMode;
+import org.thymeleaf.templateresolver.AbstractConfigurableTemplateResolver;
+import org.thymeleaf.templateresolver.ServletContextTemplateResolver;
+
+import javax.servlet.ServletContext;
+
+public class ThymeleafUtil {
+
+ private ThymeleafUtil() {
+ }
+
+ public static TemplateEngine getTemplateEngine(final ServletContext servletContext) {
+ ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(servletContext);
+ // HTML is the default mode, but we set it anyway for better understanding of code
+ templateResolver.setTemplateMode(TemplateMode.HTML);
+ // This will convert "home" to "/WEB-INF/templates/home.html"
+ templateResolver.setPrefix("/WEB-INF/templates/");
+ templateResolver.setSuffix(".html");
+ // Template cache TTL=1h. If not set, entries would be cached until expelled
+ templateResolver.setCacheTTLMs(1000L);
+
+ // Cache is set to true by default. Set to false if you want templates to
+ // be automatically updated when modified.
+ //templateResolver.setCacheable(true);
+
+ final TemplateEngine templateEngine = new TemplateEngine();
+ templateEngine.setTemplateResolver(templateResolver);
+
+ return templateEngine;
+ }
+
+}
diff --git a/src/main/java/ru/javaops/masterjava/xml/util/XPathProcessor.java b/upload/src/main/java/ru/javaops/masterjava/xml/util/XPathProcessor.java
similarity index 100%
rename from src/main/java/ru/javaops/masterjava/xml/util/XPathProcessor.java
rename to upload/src/main/java/ru/javaops/masterjava/xml/util/XPathProcessor.java
diff --git a/src/main/java/ru/javaops/masterjava/xml/util/XsltProcessor.java b/upload/src/main/java/ru/javaops/masterjava/xml/util/XsltProcessor.java
similarity index 100%
rename from src/main/java/ru/javaops/masterjava/xml/util/XsltProcessor.java
rename to upload/src/main/java/ru/javaops/masterjava/xml/util/XsltProcessor.java
diff --git a/src/main/resources/cities.xsl b/upload/src/main/resources/cities.xsl
similarity index 100%
rename from src/main/resources/cities.xsl
rename to upload/src/main/resources/cities.xsl
diff --git a/src/main/resources/groups.xsl b/upload/src/main/resources/groups.xsl
similarity index 100%
rename from src/main/resources/groups.xsl
rename to upload/src/main/resources/groups.xsl
diff --git a/src/test/resources/payload.xml b/upload/src/main/resources/payload.xml
similarity index 100%
rename from src/test/resources/payload.xml
rename to upload/src/main/resources/payload.xml
diff --git a/src/main/resources/payload.xsd b/upload/src/main/resources/payload.xsd
similarity index 100%
rename from src/main/resources/payload.xsd
rename to upload/src/main/resources/payload.xsd
diff --git a/upload/src/main/webapp/WEB-INF/templates/exception.html b/upload/src/main/webapp/WEB-INF/templates/exception.html
new file mode 100644
index 0000000..0b5216e
--- /dev/null
+++ b/upload/src/main/webapp/WEB-INF/templates/exception.html
@@ -0,0 +1,20 @@
+
+
+
+
+ Export XML
+
+
+
+
+
+
Application error
+
+
exception.message
\
+
+
+
+
+
\ No newline at end of file
diff --git a/upload/src/main/webapp/WEB-INF/templates/export.html b/upload/src/main/webapp/WEB-INF/templates/export.html
new file mode 100644
index 0000000..b6066f3
--- /dev/null
+++ b/upload/src/main/webapp/WEB-INF/templates/export.html
@@ -0,0 +1,18 @@
+
+
+
+
+ Title
+
+
+
+
+
\ No newline at end of file
diff --git a/upload/src/main/webapp/WEB-INF/templates/result.html b/upload/src/main/webapp/WEB-INF/templates/result.html
new file mode 100644
index 0000000..01d611f
--- /dev/null
+++ b/upload/src/main/webapp/WEB-INF/templates/result.html
@@ -0,0 +1,25 @@
+
+
+
+
+ Title
+
+
+
+
+
+ | Full Name |
+ Email |
+ Flag |
+
+
+
+
+ |
+ |
+ |
+
+
+
+
+
\ No newline at end of file
diff --git a/webapp/pom.xml b/webapp/pom.xml
new file mode 100644
index 0000000..7dfa438
--- /dev/null
+++ b/webapp/pom.xml
@@ -0,0 +1,27 @@
+
+
+ 4.0.0
+
+
+ ru.javaops
+ parent-war
+ ../parent-war/pom.xml
+ 2.0-SNAPSHOT
+
+
+ webapp
+ 1.0-SNAPSHOT
+ war
+ Webapp
+
+
+
+ ru.javaops
+ mail-api
+ 1.0-SNAPSHOT
+
+
+
+
\ No newline at end of file