1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.mycore.wcms2.navigation;
20
21 import java.io.IOException;
22 import java.io.OutputStream;
23 import java.net.MalformedURLException;
24 import java.net.URL;
25 import java.nio.file.Files;
26 import java.nio.file.Paths;
27 import java.util.Optional;
28
29 import org.apache.logging.log4j.LogManager;
30 import org.apache.logging.log4j.Logger;
31 import org.jdom2.Document;
32 import org.jdom2.Element;
33 import org.jdom2.JDOMException;
34 import org.jdom2.input.SAXBuilder;
35 import org.jdom2.output.Format;
36 import org.jdom2.output.XMLOutputter;
37 import org.mycore.common.config.MCRConfiguration2;
38 import org.mycore.common.content.MCRURLContent;
39 import org.mycore.tools.MyCoReWebPageProvider;
40 import org.mycore.wcms2.MCRWebPagesSynchronizer;
41 import org.xml.sax.SAXException;
42
43 import com.google.gson.JsonArray;
44 import com.google.gson.JsonElement;
45 import com.google.gson.JsonObject;
46
47 import jakarta.ws.rs.WebApplicationException;
48 import jakarta.ws.rs.core.MediaType;
49 import jakarta.ws.rs.core.Response;
50 import jakarta.ws.rs.core.Response.Status;
51
52
53
54
55
56
57 public class MCRWCMSContentManager {
58
59 private static final Logger LOGGER = LogManager.getLogger(MCRWCMSContentManager.class);
60
61 private MCRWCMSSectionProvider sectionProvider;
62
63 public enum ErrorType {
64 notExist, invalidFile, notMyCoReWebPage, invalidDirectory, couldNotSave, couldNotMove
65 }
66
67 public MCRWCMSContentManager() {
68 this.sectionProvider = MCRConfiguration2.<MCRWCMSSectionProvider>getInstanceOf("MCR.WCMS2.sectionProvider")
69 .orElseGet(MCRWCMSDefaultSectionProvider::new);
70 }
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94 public JsonObject getContent(String webpageId) throws IOException, JDOMException, SAXException {
95 boolean isXML = webpageId.endsWith(".xml");
96 URL resourceURL = null;
97 try {
98 resourceURL = MCRWebPagesSynchronizer.getURL(webpageId);
99 } catch (MalformedURLException e) {
100 throwError(ErrorType.invalidDirectory, webpageId);
101 }
102
103 if (!isXML) {
104 throwError(ErrorType.invalidFile, webpageId);
105 }
106 Document doc = null;
107 if (resourceURL == null) {
108 MyCoReWebPageProvider wpp = new MyCoReWebPageProvider();
109 wpp.addSection("neuer Eintrag", new Element("p").setText("TODO"), "de");
110 doc = wpp.getXML();
111 } else {
112 doc = new MCRURLContent(resourceURL).asXML();
113 }
114 Element rootElement = doc.getRootElement();
115 if (!"MyCoReWebPage".equals(rootElement.getName())) {
116 throwError(ErrorType.notMyCoReWebPage, webpageId);
117 }
118
119 return getContent(rootElement);
120 }
121
122 public JsonObject getContent(Element e) {
123 JsonArray sectionArray = this.sectionProvider.toJSON(e);
124 JsonObject content = new JsonObject();
125 content.addProperty("type", "content");
126 content.add("content", sectionArray);
127 return content;
128 }
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152 public void save(JsonArray items) {
153 XMLOutputter out = new XMLOutputter(Format.getRawFormat().setEncoding("UTF-8"));
154 for (JsonElement e : items) {
155 validateContent(e).ifPresent(item -> {
156 String webpageId = getWebPageId(item).get();
157 if (!webpageId.endsWith(".xml")) {
158 throwError(ErrorType.invalidFile, webpageId);
159 }
160 JsonArray content = item.get("content").getAsJsonArray();
161 Element mycoreWebpage = this.sectionProvider.fromJSON(content);
162
163 try (OutputStream fout = MCRWebPagesSynchronizer.getOutputStream(webpageId)) {
164 out.output(new Document(mycoreWebpage), fout);
165 } catch (IOException | RuntimeException exc) {
166 LOGGER.error("Error while saving {}", webpageId, exc);
167 throwError(ErrorType.couldNotSave, webpageId);
168 }
169 });
170 }
171 }
172
173 private Optional<String> getWebPageId(JsonObject item) {
174 JsonElement webpageIdElement = item.has("href") ? item.get("href")
175 : (item.has("hrefStartingPage") ? item
176 .get("hrefStartingPage") : null);
177 if (webpageIdElement == null || !webpageIdElement.isJsonPrimitive()) {
178 return Optional.empty();
179 }
180 return Optional.of(webpageIdElement)
181 .map(JsonElement::getAsString);
182 }
183
184 private Optional<JsonObject> validateContent(JsonElement e) {
185 if (!e.isJsonObject()) {
186 LOGGER.warn("Invalid json element in items {}", e);
187 return Optional.empty();
188 }
189 JsonObject item = e.getAsJsonObject();
190 if (!item.has("dirty") || !item.get("dirty").getAsBoolean()) {
191 return Optional.empty();
192 }
193
194
195 if (!getWebPageId(item).isPresent() || !item.has("content") || !item.get("content").isJsonArray()) {
196 return Optional.empty();
197 }
198 return Optional.of(item);
199 }
200
201 public void move(String from, String to) {
202 try {
203
204 URL fromURL = MCRWebPagesSynchronizer.getURL(from);
205 Document document;
206 if (fromURL == null) {
207
208 MyCoReWebPageProvider wpp = new MyCoReWebPageProvider();
209 wpp.addSection("neuer Eintrag", new Element("p").setText("TODO"), "de");
210 document = wpp.getXML();
211 } else {
212 SAXBuilder builder = new SAXBuilder();
213 document = builder.build(fromURL);
214 }
215
216 XMLOutputter out = new XMLOutputter(Format.getPrettyFormat().setEncoding("UTF-8"));
217 try (OutputStream fout = MCRWebPagesSynchronizer.getOutputStream(to)) {
218 out.output(document, fout);
219 }
220
221 if (fromURL != null) {
222 Files.delete(Paths.get(fromURL.toURI()));
223 }
224 } catch (Exception exc) {
225 LOGGER.error("Error moving {} to {}", from, to, exc);
226 throwError(ErrorType.couldNotMove, to);
227 }
228 }
229
230
231
232
233
234
235
236
237 private void throwError(ErrorType errorType, String webpageId) {
238 JsonObject error = new JsonObject();
239 error.addProperty("type", errorType.name());
240 error.addProperty("webpageId", webpageId);
241 Response response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(error.toString())
242 .type(MediaType.APPLICATION_JSON).build();
243 throw new WebApplicationException(response);
244 }
245
246 }