]> git.argeo.org Git - gpl/argeo-slc.git/blob - JcrRepositoryBackup.java
977bf8786d1362f3ae12be33558e80cf1167d2b2
[gpl/argeo-slc.git] / JcrRepositoryBackup.java
1 package org.argeo.slc.lib.jcr;
2
3 import java.util.UUID;
4 import java.util.jar.Attributes;
5 import java.util.jar.JarEntry;
6 import java.util.jar.JarOutputStream;
7 import java.util.jar.Manifest;
8
9 import javax.jcr.Credentials;
10 import javax.jcr.Node;
11 import javax.jcr.NodeIterator;
12 import javax.jcr.Repository;
13 import javax.jcr.RepositoryFactory;
14 import javax.jcr.Session;
15 import javax.jcr.SimpleCredentials;
16
17 import org.apache.commons.io.IOUtils;
18 import org.apache.commons.logging.Log;
19 import org.apache.commons.logging.LogFactory;
20 import org.apache.commons.vfs2.FileObject;
21 import org.apache.commons.vfs2.FileSelectInfo;
22 import org.apache.commons.vfs2.FileSelector;
23 import org.apache.commons.vfs2.FileSystemException;
24 import org.apache.commons.vfs2.FileSystemManager;
25 import org.argeo.jcr.JcrUtils;
26 import org.argeo.api.NodeUtils;
27 import org.argeo.slc.SlcException;
28
29 /** Backups a JCR repository */
30 public class JcrRepositoryBackup implements Runnable {
31 private final static Log log = LogFactory.getLog(JcrRepositoryBackup.class);
32
33 private String sourceRepo;
34 private String sourceDatastore;
35 private String targetFile;
36
37 private String sourceWksp;
38
39 private String sourceUsername;
40 private char[] sourcePassword;
41
42 private RepositoryFactory repositoryFactory;
43 private FileSystemManager fileSystemManager;
44
45 public void run() {
46 Session sourceDefaultSession = null;
47 try {
48 long begin = System.currentTimeMillis();
49
50 FileObject archiveRoot = fileSystemManager.resolveFile(targetFile);
51 archiveRoot.createFolder();
52
53 String datastoreFolderName = "datastore";
54 if (hasDatastore())
55 backupDataStore(archiveRoot.resolveFile(datastoreFolderName));
56
57 Repository sourceRepository = NodeUtils.getRepositoryByUri(
58 repositoryFactory, sourceRepo);
59 Credentials sourceCredentials = null;
60 if (sourceUsername != null)
61 sourceCredentials = new SimpleCredentials(sourceUsername,
62 sourcePassword);
63
64 sourceDefaultSession = sourceRepository.login(sourceCredentials);
65 for (String sourceWorkspaceName : sourceDefaultSession
66 .getWorkspace().getAccessibleWorkspaceNames()) {
67 if (Thread.interrupted()) {
68 log.error("Workspace backup interrupted");
69 Thread.currentThread().interrupt();
70 return;
71 }
72
73 if (sourceWksp != null && !sourceWksp.trim().equals("")
74 && !sourceWorkspaceName.equals(sourceWksp))
75 continue;
76 Session sourceSession = null;
77 JarOutputStream out = null;
78 FileObject workspaceBackup = null;
79 try {
80 Manifest manifest = new Manifest();
81 manifest.getMainAttributes().put(
82 Attributes.Name.MANIFEST_VERSION, "1.0");
83 manifest.getMainAttributes().putValue("Backup-UUID",
84 UUID.randomUUID().toString());
85 manifest.getMainAttributes().putValue("Backup-Timestamp",
86 Long.toString(System.currentTimeMillis()));
87 manifest.getMainAttributes().putValue(
88 "Backup-JCR-Workspace", sourceWorkspaceName);
89 workspaceBackup = fileSystemManager.resolveFile(targetFile
90 + "/" + sourceWorkspaceName + ".jar");
91
92 out = new JarOutputStream(workspaceBackup.getContent()
93 .getOutputStream(), manifest);
94 sourceSession = sourceRepository.login(sourceCredentials,
95 sourceWorkspaceName);
96 backupWorkspace(sourceSession, out);
97 } finally {
98 JcrUtils.logoutQuietly(sourceSession);
99 IOUtils.closeQuietly(out);
100 if (workspaceBackup != null)
101 workspaceBackup.close();
102 }
103 }
104
105 // in case some binaries have been added during the backup
106 if (hasDatastore())
107 backupDataStore(archiveRoot.resolveFile(datastoreFolderName));
108
109 long duration = (System.currentTimeMillis() - begin) / 1000;// s
110 log.info("Backed-up " + sourceRepo + " in " + (duration / 60)
111 + "min " + (duration % 60) + "s");
112 } catch (Exception e) {
113 throw new SlcException("Cannot backup " + sourceRepo, e);
114 } finally {
115 JcrUtils.logoutQuietly(sourceDefaultSession);
116 }
117 }
118
119 protected Boolean hasDatastore() {
120 return sourceDatastore != null && !sourceDatastore.trim().equals("");
121 }
122
123 protected void backupWorkspace(Session sourceSession, JarOutputStream out) {
124 try {
125 if (log.isTraceEnabled())
126 log.trace("Backup " + sourceSession.getWorkspace().getName()
127 + "...");
128 Boolean skipBinaries = hasDatastore();
129 for (NodeIterator it = sourceSession.getRootNode().getNodes(); it
130 .hasNext();) {
131 if (Thread.interrupted()) {
132 log.error("Node backup interrupted");
133 Thread.currentThread().interrupt();
134 return;
135 }
136 Node node = it.nextNode();
137 JarEntry entry = new JarEntry(node.getPath());
138 out.putNextEntry(entry);
139 sourceSession.exportSystemView(node.getPath(), out,
140 skipBinaries, false);
141 out.flush();
142 out.closeEntry();
143 }
144 if (log.isDebugEnabled())
145 log.debug("Backed up " + sourceSession.getWorkspace().getName());
146 } catch (Exception e) {
147 throw new SlcException("Cannot backup "
148 + sourceSession.getWorkspace().getName(), e);
149 }
150 }
151
152 protected void backupDataStore(final FileObject targetDatastore) {
153 try {
154 targetDatastore.createFolder();
155 final FileObject sourceDataStore = fileSystemManager
156 .resolveFile(sourceDatastore);
157 if (log.isDebugEnabled())
158 log.debug("Backup " + sourceDatastore);
159 targetDatastore.copyFrom(sourceDataStore, new FileSelector() {
160 public boolean traverseDescendents(FileSelectInfo fileInfo)
161 throws Exception {
162 return true;
163 }
164
165 public boolean includeFile(FileSelectInfo fileInfo)
166 throws Exception {
167 String relativeName = fileInfo
168 .getFile()
169 .getName()
170 .getPath()
171 .substring(
172 sourceDataStore.getName().getPath()
173 .length());
174 FileObject target = targetDatastore
175 .resolveFile(relativeName);
176 if (target.exists()) {
177 return false;
178 } else {
179 return true;
180 }
181 }
182 });
183 if (log.isDebugEnabled())
184 log.debug("Backed-up " + sourceDatastore);
185 } catch (FileSystemException e) {
186 throw new SlcException("Cannot backup datastore", e);
187 }
188 }
189
190 public void setSourceRepo(String sourceRepo) {
191 this.sourceRepo = sourceRepo;
192 }
193
194 public void setSourceWksp(String sourceWksp) {
195 this.sourceWksp = sourceWksp;
196 }
197
198 public void setRepositoryFactory(RepositoryFactory repositoryFactory) {
199 this.repositoryFactory = repositoryFactory;
200 }
201
202 public void setSourceUsername(String sourceUsername) {
203 this.sourceUsername = sourceUsername;
204 }
205
206 public void setSourcePassword(char[] sourcePassword) {
207 this.sourcePassword = sourcePassword;
208 }
209
210 public void setFileSystemManager(FileSystemManager fileSystemManager) {
211 this.fileSystemManager = fileSystemManager;
212 }
213
214 public void setTargetFile(String targetFile) {
215 this.targetFile = targetFile;
216 }
217
218 public void setSourceDatastore(String sourceDatastore) {
219 this.sourceDatastore = sourceDatastore;
220 }
221
222 }