2 * Copyright (C) 2007-2012 Argeo GmbH
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org
.argeo
.slc
.lib
.jcr
;
18 import java
.util
.UUID
;
19 import java
.util
.jar
.Attributes
;
20 import java
.util
.jar
.JarEntry
;
21 import java
.util
.jar
.JarOutputStream
;
22 import java
.util
.jar
.Manifest
;
24 import javax
.jcr
.Credentials
;
25 import javax
.jcr
.Node
;
26 import javax
.jcr
.NodeIterator
;
27 import javax
.jcr
.Repository
;
28 import javax
.jcr
.RepositoryFactory
;
29 import javax
.jcr
.Session
;
30 import javax
.jcr
.SimpleCredentials
;
32 import org
.apache
.commons
.io
.IOUtils
;
33 import org
.apache
.commons
.logging
.Log
;
34 import org
.apache
.commons
.logging
.LogFactory
;
35 import org
.apache
.commons
.vfs
.FileObject
;
36 import org
.apache
.commons
.vfs
.FileSelectInfo
;
37 import org
.apache
.commons
.vfs
.FileSelector
;
38 import org
.apache
.commons
.vfs
.FileSystemException
;
39 import org
.apache
.commons
.vfs
.FileSystemManager
;
40 import org
.argeo
.jcr
.ArgeoJcrUtils
;
41 import org
.argeo
.jcr
.JcrUtils
;
42 import org
.argeo
.slc
.SlcException
;
44 /** Backups a JCR repository */
45 public class JcrRepositoryBackup
implements Runnable
{
46 private final static Log log
= LogFactory
.getLog(JcrRepositoryBackup
.class);
48 private String sourceRepo
;
49 private String sourceDatastore
;
50 private String targetFile
;
52 private String sourceWksp
;
54 private String sourceUsername
;
55 private char[] sourcePassword
;
57 private RepositoryFactory repositoryFactory
;
58 private FileSystemManager fileSystemManager
;
61 Session sourceDefaultSession
= null;
63 long begin
= System
.currentTimeMillis();
65 FileObject archiveRoot
= fileSystemManager
.resolveFile(targetFile
);
66 archiveRoot
.createFolder();
68 String datastoreFolderName
= "datastore";
70 backupDataStore(archiveRoot
.resolveFile(datastoreFolderName
));
72 Repository sourceRepository
= ArgeoJcrUtils
.getRepositoryByUri(
73 repositoryFactory
, sourceRepo
);
74 Credentials sourceCredentials
= null;
75 if (sourceUsername
!= null)
76 sourceCredentials
= new SimpleCredentials(sourceUsername
,
79 sourceDefaultSession
= sourceRepository
.login(sourceCredentials
);
80 for (String sourceWorkspaceName
: sourceDefaultSession
81 .getWorkspace().getAccessibleWorkspaceNames()) {
82 if (Thread
.interrupted()) {
83 log
.error("Workspace backup interrupted");
84 Thread
.currentThread().interrupt();
88 if (sourceWksp
!= null && !sourceWksp
.trim().equals("")
89 && !sourceWorkspaceName
.equals(sourceWksp
))
91 Session sourceSession
= null;
92 JarOutputStream out
= null;
93 FileObject workspaceBackup
= null;
95 Manifest manifest
= new Manifest();
96 manifest
.getMainAttributes().put(
97 Attributes
.Name
.MANIFEST_VERSION
, "1.0");
98 manifest
.getMainAttributes().putValue("Backup-UUID",
99 UUID
.randomUUID().toString());
100 manifest
.getMainAttributes().putValue("Backup-Timestamp",
101 Long
.toString(System
.currentTimeMillis()));
102 manifest
.getMainAttributes().putValue(
103 "Backup-JCR-Workspace", sourceWorkspaceName
);
104 workspaceBackup
= fileSystemManager
.resolveFile(targetFile
105 + "/" + sourceWorkspaceName
+ ".jar");
107 out
= new JarOutputStream(workspaceBackup
.getContent()
108 .getOutputStream(), manifest
);
109 sourceSession
= sourceRepository
.login(sourceCredentials
,
110 sourceWorkspaceName
);
111 backupWorkspace(sourceSession
, out
);
113 JcrUtils
.logoutQuietly(sourceSession
);
114 IOUtils
.closeQuietly(out
);
115 if (workspaceBackup
!= null)
116 workspaceBackup
.close();
120 // in case some binaries have been added during the backup
122 backupDataStore(archiveRoot
.resolveFile(datastoreFolderName
));
124 long duration
= (System
.currentTimeMillis() - begin
) / 1000;// s
125 log
.info("Backed-up " + sourceRepo
+ " in " + (duration
/ 60)
126 + "min " + (duration
% 60) + "s");
127 } catch (Exception e
) {
128 throw new SlcException("Cannot backup " + sourceRepo
, e
);
130 JcrUtils
.logoutQuietly(sourceDefaultSession
);
134 protected Boolean
hasDatastore() {
135 return sourceDatastore
!= null && !sourceDatastore
.trim().equals("");
138 protected void backupWorkspace(Session sourceSession
, JarOutputStream out
) {
140 if (log
.isTraceEnabled())
141 log
.trace("Backup " + sourceSession
.getWorkspace().getName()
143 Boolean skipBinaries
= hasDatastore();
144 for (NodeIterator it
= sourceSession
.getRootNode().getNodes(); it
146 if (Thread
.interrupted()) {
147 log
.error("Node backup interrupted");
148 Thread
.currentThread().interrupt();
151 Node node
= it
.nextNode();
152 JarEntry entry
= new JarEntry(node
.getPath());
153 out
.putNextEntry(entry
);
154 sourceSession
.exportSystemView(node
.getPath(), out
,
155 skipBinaries
, false);
159 if (log
.isDebugEnabled())
160 log
.debug("Backed up " + sourceSession
.getWorkspace().getName());
161 } catch (Exception e
) {
162 throw new SlcException("Cannot backup "
163 + sourceSession
.getWorkspace().getName(), e
);
167 protected void backupDataStore(final FileObject targetDatastore
) {
169 targetDatastore
.createFolder();
170 final FileObject sourceDataStore
= fileSystemManager
171 .resolveFile(sourceDatastore
);
172 if (log
.isDebugEnabled())
173 log
.debug("Backup " + sourceDatastore
);
174 targetDatastore
.copyFrom(sourceDataStore
, new FileSelector() {
175 public boolean traverseDescendents(FileSelectInfo fileInfo
)
180 public boolean includeFile(FileSelectInfo fileInfo
)
182 String relativeName
= fileInfo
187 sourceDataStore
.getName().getPath()
189 FileObject target
= targetDatastore
190 .resolveFile(relativeName
);
191 if (target
.exists()) {
198 if (log
.isDebugEnabled())
199 log
.debug("Backed-up " + sourceDatastore
);
200 } catch (FileSystemException e
) {
201 throw new SlcException("Cannot backup datastore", e
);
205 public void setSourceRepo(String sourceRepo
) {
206 this.sourceRepo
= sourceRepo
;
209 public void setSourceWksp(String sourceWksp
) {
210 this.sourceWksp
= sourceWksp
;
213 public void setRepositoryFactory(RepositoryFactory repositoryFactory
) {
214 this.repositoryFactory
= repositoryFactory
;
217 public void setSourceUsername(String sourceUsername
) {
218 this.sourceUsername
= sourceUsername
;
221 public void setSourcePassword(char[] sourcePassword
) {
222 this.sourcePassword
= sourcePassword
;
225 public void setFileSystemManager(FileSystemManager fileSystemManager
) {
226 this.fileSystemManager
= fileSystemManager
;
229 public void setTargetFile(String targetFile
) {
230 this.targetFile
= targetFile
;
233 public void setSourceDatastore(String sourceDatastore
) {
234 this.sourceDatastore
= sourceDatastore
;