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