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
.repo
;
18 import java
.util
.Calendar
;
20 import javax
.jcr
.Credentials
;
21 import javax
.jcr
.ImportUUIDBehavior
;
22 import javax
.jcr
.NoSuchWorkspaceException
;
23 import javax
.jcr
.Node
;
24 import javax
.jcr
.NodeIterator
;
25 import javax
.jcr
.Property
;
26 import javax
.jcr
.Repository
;
27 import javax
.jcr
.RepositoryException
;
28 import javax
.jcr
.RepositoryFactory
;
29 import javax
.jcr
.Session
;
30 import javax
.jcr
.SimpleCredentials
;
31 import javax
.jcr
.nodetype
.NodeType
;
33 import org
.apache
.commons
.logging
.Log
;
34 import org
.apache
.commons
.logging
.LogFactory
;
35 import org
.argeo
.jcr
.ArgeoJcrUtils
;
36 import org
.argeo
.jcr
.JcrUtils
;
37 import org
.argeo
.slc
.SlcException
;
38 import org
.xml
.sax
.ContentHandler
;
39 import org
.xml
.sax
.SAXException
;
41 /** Sync to from software repositories */
42 public class RepoSync
implements Runnable
{
43 private final static Log log
= LogFactory
.getLog(RepoSync
.class);
45 private String sourceRepo
;
46 private String targetRepo
;
48 private String sourceWksp
;
50 private String sourceUsername
;
51 private char[] sourcePassword
;
53 private RepositoryFactory repositoryFactory
;
56 Session sourceDefaultSession
= null;
57 Session targetDefaultSession
= null;
59 long begin
= System
.currentTimeMillis();
61 Repository sourceRepository
= ArgeoJcrUtils
.getRepositoryByUri(
62 repositoryFactory
, sourceRepo
);
63 Repository targetRepository
= ArgeoJcrUtils
.getRepositoryByUri(
64 repositoryFactory
, targetRepo
);
65 Credentials sourceCredentials
= null;
66 if (sourceUsername
!= null)
67 sourceCredentials
= new SimpleCredentials(sourceUsername
,
69 Credentials targetCredentials
= null;
71 sourceDefaultSession
= sourceRepository
.login(sourceCredentials
);
72 targetDefaultSession
= targetRepository
.login(targetCredentials
);
73 for (String sourceWorkspaceName
: sourceDefaultSession
74 .getWorkspace().getAccessibleWorkspaceNames()) {
75 Session sourceSession
= null;
76 Session targetSession
= null;
79 targetSession
= targetRepository
.login(
80 targetCredentials
, sourceWorkspaceName
);
81 } catch (NoSuchWorkspaceException e
) {
82 targetDefaultSession
.getWorkspace().createWorkspace(
84 targetSession
= targetRepository
.login(
85 targetCredentials
, sourceWorkspaceName
);
87 sourceSession
= sourceRepository
.login(sourceCredentials
,
89 syncWorkspace(sourceSession
, targetSession
);
91 JcrUtils
.logoutQuietly(sourceSession
);
92 JcrUtils
.logoutQuietly(targetSession
);
95 // Session sourceSession = sourceRepository.login(sourceCredentials,
98 // Credentials targetCredentials = null;
99 // Session targetSession = targetRepository.login(targetCredentials,
102 // Long count = JcrUtils.copyFiles(sourceSession.getRootNode(),
103 // targetSession.getRootNode(), true, null);
105 long duration
= (System
.currentTimeMillis() - begin
) / 1000;// s
106 log
.info("Sync " + sourceRepo
+ " to " + targetRepo
+ " in "
109 + "min " + (duration
% 60) + "s");
110 } catch (RepositoryException e
) {
111 throw new SlcException("Cannot sync " + sourceRepo
+ " to "
114 JcrUtils
.logoutQuietly(sourceDefaultSession
);
115 JcrUtils
.logoutQuietly(targetDefaultSession
);
119 protected void syncWorkspace(Session sourceSession
, Session targetSession
) {
121 if (log
.isDebugEnabled())
122 log
.debug("Syncing " + sourceSession
.getWorkspace().getName()
124 for (NodeIterator it
= sourceSession
.getRootNode().getNodes(); it
126 Node node
= it
.nextNode();
127 if (node
.getName().equals("jcr:system"))
129 // ContentHandler targetHandler = targetSession
131 // .getImportContentHandler(
133 // ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING);
134 // sourceSession.exportSystemView(node.getPath(), targetHandler,
136 // if (log.isDebugEnabled())
137 // log.debug(" " + node.getPath());
138 syncNode(node
, targetSession
.getRootNode());
140 if (log
.isDebugEnabled())
141 log
.debug("Synced " + sourceSession
.getWorkspace().getName());
142 } catch (Exception e
) {
143 throw new SlcException("Cannot sync "
144 + sourceSession
.getWorkspace().getName() + " to "
145 + targetSession
.getWorkspace().getName(), e
);
149 protected void syncNode(Node sourceNode
, Node targetParentNode
)
150 throws RepositoryException
, SAXException
{
151 Boolean noRecurse
= noRecurse(sourceNode
);
152 if (!targetParentNode
.hasNode(sourceNode
.getName())) {
153 ContentHandler contentHandler
= targetParentNode
156 .getImportContentHandler(targetParentNode
.getPath(),
157 ImportUUIDBehavior
.IMPORT_UUID_COLLISION_THROW
);
158 sourceNode
.getSession().exportSystemView(sourceNode
.getPath(),
159 contentHandler
, false, noRecurse
);
160 if (log
.isDebugEnabled())
161 log
.debug("Add " + sourceNode
.getPath());
163 Node targetNode
= targetParentNode
.getNode(sourceNode
.getName());
164 if (sourceNode
.isNodeType(NodeType
.MIX_LAST_MODIFIED
)) {
165 Calendar sourceLastModified
= sourceNode
.getProperty(
166 Property
.JCR_LAST_MODIFIED
).getDate();
167 Calendar targetLastModified
= null;
168 if (targetNode
.isNodeType(NodeType
.MIX_LAST_MODIFIED
)) {
169 targetLastModified
= targetNode
.getProperty(
170 Property
.JCR_LAST_MODIFIED
).getDate();
173 if (targetLastModified
== null
174 || targetLastModified
.before(sourceLastModified
)) {
175 ContentHandler contentHandler
= targetParentNode
178 .getImportContentHandler(
179 targetParentNode
.getPath(),
180 ImportUUIDBehavior
.IMPORT_UUID_COLLISION_REMOVE_EXISTING
);
181 sourceNode
.getSession().exportSystemView(
182 sourceNode
.getPath(), contentHandler
, false,
184 if (log
.isDebugEnabled())
185 log
.debug("Update " + targetNode
.getPath());
187 if (log
.isDebugEnabled())
188 log
.debug("Skip up to date " + targetNode
.getPath());
195 Node targetNode
= targetParentNode
.getNode(sourceNode
.getName());
196 for (NodeIterator it
= sourceNode
.getNodes(); it
.hasNext();) {
197 syncNode(it
.nextNode(), targetNode
);
203 protected Boolean
noRecurse(Node sourceNode
) throws RepositoryException
{
204 if (sourceNode
.isNodeType(NodeType
.NT_FILE
))
209 public void setSourceRepo(String sourceRepo
) {
210 this.sourceRepo
= sourceRepo
;
213 public void setTargetRepo(String targetRepo
) {
214 this.targetRepo
= targetRepo
;
217 public void setSourceWksp(String sourceWksp
) {
218 this.sourceWksp
= sourceWksp
;
221 public void setRepositoryFactory(RepositoryFactory repositoryFactory
) {
222 this.repositoryFactory
= repositoryFactory
;
225 public void setSourceUsername(String sourceUsername
) {
226 this.sourceUsername
= sourceUsername
;
229 public void setSourcePassword(char[] sourcePassword
) {
230 this.sourcePassword
= sourcePassword
;