1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.module.admininterface.pages;
35
36 import info.magnolia.cms.beans.config.ContentRepository;
37 import info.magnolia.cms.core.Content;
38 import info.magnolia.cms.core.Content.ContentFilter;
39 import info.magnolia.cms.core.HierarchyManager;
40 import info.magnolia.cms.core.ItemType;
41 import info.magnolia.cms.core.Path;
42 import info.magnolia.cms.i18n.MessagesManager;
43 import info.magnolia.cms.security.AccessDeniedException;
44 import info.magnolia.cms.util.AlertUtil;
45 import info.magnolia.cms.util.ContentUtil;
46 import info.magnolia.cms.util.NodeDataUtil;
47 import info.magnolia.context.MgnlContext;
48 import info.magnolia.importexport.DataTransporter;
49 import info.magnolia.module.ModuleRegistry;
50 import info.magnolia.module.admininterface.TemplatedMVCHandler;
51 import info.magnolia.module.files.BasicFileExtractor;
52 import info.magnolia.module.files.FileExtractor;
53 import info.magnolia.module.files.ModuleFileExtractorTransformer;
54 import info.magnolia.repository.RepositoryConstants;
55
56 import java.io.File;
57 import java.io.FileNotFoundException;
58 import java.io.FileOutputStream;
59 import java.io.IOException;
60 import java.util.HashSet;
61 import java.util.Iterator;
62 import java.util.Set;
63
64 import javax.jcr.PathNotFoundException;
65 import javax.jcr.RepositoryException;
66 import javax.jcr.Session;
67 import javax.servlet.http.HttpServletRequest;
68 import javax.servlet.http.HttpServletResponse;
69
70 import org.apache.commons.io.IOUtils;
71 import org.apache.commons.lang.StringEscapeUtils;
72 import org.apache.commons.lang.StringUtils;
73 import org.slf4j.Logger;
74 import org.slf4j.LoggerFactory;
75
76
77
78
79
80
81
82 public class DevelopmentUtilsPage extends TemplatedMVCHandler {
83
84 private boolean templates;
85
86 private boolean paragraphs;
87
88 private boolean dialogs;
89
90 private boolean pages;
91
92 private boolean website;
93
94 private boolean users;
95
96 private boolean groups;
97
98 private boolean roles;
99
100 private boolean virtualURIs;
101
102 private String rootdir;
103
104 private String parentpath;
105
106 private String repository;
107
108 private String module;
109
110 private ContentFilter chieldFilter;
111
112
113
114
115 public static Logger log = LoggerFactory.getLogger(DevelopmentUtilsPage.class);
116
117
118
119
120
121
122 public DevelopmentUtilsPage(String name, HttpServletRequest request, HttpServletResponse response) {
123 super(name, request, response);
124
125 rootdir = StringUtils.defaultIfEmpty(NodeDataUtil.getString(
126 RepositoryConstants.CONFIG,
127 "/modules/adminInterface/config/developmentUtils/exportpath"), "WEB-INF/bootstrap/common");
128 module = StringUtils.defaultIfEmpty(NodeDataUtil.getString(
129 RepositoryConstants.CONFIG,
130 "/modules/adminInterface/config/developmentUtils/module"), "templating");
131 }
132
133
134
135
136
137 public boolean isTemplates() {
138 return this.templates;
139 }
140
141
142
143
144
145 public boolean isParagraphs() {
146 return this.paragraphs;
147 }
148
149
150
151
152
153 public boolean isDialogs() {
154 return this.dialogs;
155 }
156
157
158
159
160
161 public boolean isPages() {
162 return this.pages;
163 }
164
165
166
167
168
169
170 public void setChieldFilter(ContentFilter chieldFilter) {
171 this.chieldFilter = chieldFilter;
172 }
173
174
175
176
177
178 public void setPages(boolean pages) {
179 this.pages = pages;
180 }
181
182
183
184
185
186 public boolean isWebsite() {
187 return this.website;
188 }
189
190
191
192
193
194 public boolean isUsers() {
195 return this.users;
196 }
197
198
199
200
201
202 public boolean isGroups() {
203 return this.groups;
204 }
205
206
207
208
209
210 public boolean isRoles() {
211 return this.roles;
212 }
213
214
215
216
217
218 public String getRootdir() {
219 return this.rootdir;
220 }
221
222
223
224
225
226 public String getParentpath() {
227 return this.parentpath;
228 }
229
230
231
232
233
234 public String getRepository() {
235 return this.repository;
236 }
237
238
239
240
241
242 public void setDialogs(boolean dialogs) {
243 this.dialogs = dialogs;
244 }
245
246
247
248
249
250 public void setParagraphs(boolean paragraphs) {
251 this.paragraphs = paragraphs;
252 }
253
254
255
256
257
258 public void setTemplates(boolean templates) {
259 this.templates = templates;
260 }
261
262
263
264
265
266 public void setRootdir(String rootdir) {
267 this.rootdir = StringEscapeUtils.escapeHtml(rootdir);
268 }
269
270
271
272
273
274 public void setWebsite(boolean website) {
275 this.website = website;
276 }
277
278
279
280
281
282 public void setParentpath(String parentpath) {
283 this.parentpath = parentpath;
284 }
285
286
287
288
289
290 public void setGroups(boolean groups) {
291 this.groups = groups;
292 }
293
294
295
296
297
298 public void setRoles(boolean roles) {
299 this.roles = roles;
300 }
301
302
303
304
305
306 public void setUsers(boolean users) {
307 this.users = users;
308 }
309
310
311
312
313
314 public String getModule() {
315 return this.module;
316 }
317
318
319
320
321
322 public void setModule(String module) {
323 this.module = module;
324 }
325
326
327
328
329
330 public void setRepository(String repository) {
331 this.repository = repository;
332 }
333
334
335
336
337
338 public boolean isVirtualURIs() {
339 return this.virtualURIs;
340 }
341
342
343
344
345
346 public void setVirtualURIs(boolean virtualURIs) {
347 this.virtualURIs = virtualURIs;
348 }
349
350 public Iterator getRepositories() {
351 return ContentRepository.getAllRepositoryNames();
352 }
353
354 public Set getModules() {
355 return ModuleRegistry.Factory.getInstance().getModuleNames();
356 }
357
358
359 public String extractModuleFiles() {
360 final FileExtractor extractor = new BasicFileExtractor();
361 try {
362 extractor.extractFiles(new ModuleFileExtractorTransformer(module));
363 AlertUtil.setMessage("Files extracted");
364 }
365 catch (IOException e) {
366 AlertUtil.setMessage("Could not extract files for module " + module + ": " + e.getMessage(), e);
367 }
368
369 return this.show();
370 }
371
372 public String reloadI18nMessages() {
373 try {
374 MessagesManager.getInstance().reload();
375 AlertUtil.setMessage("Messages reloaded.");
376 }
377 catch (Exception e) {
378 e.printStackTrace();
379 AlertUtil.setMessage("Can't reload: " + e.getMessage(), e);
380 }
381
382 return this.show();
383 }
384
385 public String backup() {
386 HierarchyManager hm = MgnlContext.getHierarchyManager(RepositoryConstants.CONFIG);
387 Session session = hm.getWorkspace().getSession();
388
389 try {
390 Content moduleroot = hm.getContent("/modules/" + module);
391 if (templates) {
392 exportChildren(RepositoryConstants.CONFIG, session, moduleroot, "templates", new ItemType[]{
393 ItemType.CONTENT,
394 ItemType.CONTENTNODE}, false);
395 }
396 if (paragraphs) {
397 exportChildren(RepositoryConstants.CONFIG, session, moduleroot, "paragraphs", new ItemType[]{
398 ItemType.CONTENT,
399 ItemType.CONTENTNODE}, false);
400 }
401 if (pages) {
402 exportChildren(RepositoryConstants.CONFIG, session, moduleroot, "pages", new ItemType[]{
403 ItemType.CONTENT,
404 ItemType.CONTENTNODE}, false);
405 }
406 if (dialogs) {
407 exportChildren(RepositoryConstants.CONFIG, session, moduleroot, "dialogs", new ItemType[]{
408 ItemType.CONTENT,
409 ItemType.CONTENTNODE}, true);
410 }
411 if (virtualURIs) {
412 exportChildren(
413 RepositoryConstants.CONFIG,
414 session,
415 moduleroot,
416 "virtualURIMapping",
417 new ItemType[]{ItemType.CONTENTNODE},
418 true);
419 }
420 AlertUtil.setMessage("Backup done to "
421 + new File(Path.getAbsoluteFileSystemPath(rootdir)).getCanonicalPath());
422 }
423 catch (Exception e) {
424 log.error(e.getMessage(), e);
425 AlertUtil.setMessage("Error while processing module " + module, e);
426 }
427
428 if (website) {
429 extractWorkspaceRoots(RepositoryConstants.WEBSITE);
430 }
431
432 if (users) {
433 backupChildren(RepositoryConstants.USERS, "/admin");
434 }
435
436 if (groups) {
437 extractWorkspaceRoots(RepositoryConstants.USER_GROUPS);
438 }
439
440 if (roles) {
441 extractWorkspaceRoots(RepositoryConstants.USER_ROLES);
442 }
443
444 return this.show();
445 }
446
447
448
449
450 private void extractWorkspaceRoots(String repositoryName) {
451 try {
452 HierarchyManager hm = MgnlContext.getHierarchyManager(repositoryName);
453 Content wesiteRoot = hm.getRoot();
454
455 Iterator children = wesiteRoot.getChildren(ContentUtil.MAGNOLIA_FILTER).iterator();
456 while (children.hasNext()) {
457 Content exported = (Content) children.next();
458 exportNode(repositoryName, hm.getWorkspace().getSession(), exported);
459 }
460 }
461 catch (Exception e) {
462 log.error(e.getMessage(), e);
463 AlertUtil.setMessage("Error while processing " + repositoryName + " repository", e);
464 }
465 }
466
467 public String backupChildren() {
468 backupChildren(this.repository, this.parentpath);
469
470 String path = Path.getAbsoluteFileSystemPath(rootdir);
471
472 try {
473 path = new File(path).getCanonicalPath();
474 }
475 catch (IOException e) {
476
477 }
478
479 AlertUtil.setMessage("Backup done to " + path);
480
481 return this.show();
482 }
483
484 private void backupChildren(String repository, String parentpath) {
485 HierarchyManager hm = MgnlContext.getHierarchyManager(repository);
486
487 Content parentNode = null;
488 try {
489 parentNode = hm.getContent(parentpath);
490 }
491 catch (RepositoryException e) {
492
493 return;
494 }
495 try {
496 this.chieldFilter = this.chieldFilter!=null?this.chieldFilter:ContentUtil.ALL_NODES_EXCEPT_JCR_CONTENT_FILTER;
497 Iterator children = parentNode.getChildren(this.chieldFilter).iterator();
498 while (children.hasNext()) {
499 Content exported = (Content) children.next();
500 exportNode(repository, hm.getWorkspace().getSession(), exported);
501 }
502
503 }
504 catch (Exception e) {
505 log.error(e.getMessage(), e);
506 AlertUtil.setMessage("Error while processing actions", e);
507 }
508
509 }
510
511
512
513
514
515
516
517
518
519
520
521 private void exportChildren(String repository, Session session, Content moduleroot, String path,
522 ItemType[] itemTypes, boolean exportContentContainingContentNodes) throws PathNotFoundException,
523 RepositoryException, AccessDeniedException, FileNotFoundException, IOException {
524 Content templateRoot = null;
525 try {
526 templateRoot = moduleroot.getContent(path);
527 }
528 catch (PathNotFoundException e) {
529
530 return;
531 }
532
533
534 Set alreadyExported = new HashSet();
535
536 Iterator children = ContentUtil.collectAllChildren(templateRoot, itemTypes).iterator();
537 while (children.hasNext()) {
538 Content exported = (Content) children.next();
539 if (!exported.getNodeDataCollection().isEmpty()
540 || (exportContentContainingContentNodes && exported.hasChildren(ItemType.CONTENTNODE.getSystemName()))) {
541
542 String current = exported.getHandle();
543 boolean dontexport = false;
544
545 for (Iterator iterator = alreadyExported.iterator(); iterator.hasNext();) {
546 String already = (String) iterator.next();
547 if (current.startsWith(already)) {
548 dontexport = true;
549 break;
550 }
551 }
552
553 if (!dontexport) {
554 alreadyExported.add(exported.getHandle() + "/");
555 exportNode(repository, session, exported);
556 }
557 }
558 }
559 }
560
561
562
563
564
565
566
567 private void exportNode(String repository, Session session, Content exported) throws FileNotFoundException,
568 IOException {
569 String handle = exported.getHandle();
570 String xmlName = repository + StringUtils.replace(handle, "/", ".") + ".xml";
571 xmlName = DataTransporter.encodePath(xmlName, ".", "UTF-8");
572
573 File folder = new File(Path.getAbsoluteFileSystemPath(rootdir));
574 folder.mkdirs();
575 File xmlFile = new File(folder.getAbsoluteFile(), xmlName);
576 FileOutputStream fos = new FileOutputStream(xmlFile);
577
578 try {
579 DataTransporter.executeExport(fos, false, true, session, handle, repository, DataTransporter.XML);
580 }
581 finally {
582 IOUtils.closeQuietly(fos);
583 }
584 }
585 }