View Javadoc
1   /*
2    * Copyright (C) 2007-2012 Argeo GmbH
3    *
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
7    *
8    *         http://www.apache.org/licenses/LICENSE-2.0
9    *
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.
15   */
16  package org.argeo.slc.client.ui.dist.commands;
17  
18  import javax.jcr.Credentials;
19  import javax.jcr.NoSuchWorkspaceException;
20  import javax.jcr.Node;
21  import javax.jcr.Repository;
22  import javax.jcr.RepositoryException;
23  import javax.jcr.RepositoryFactory;
24  import javax.jcr.Session;
25  import javax.jcr.query.Query;
26  import javax.jcr.query.QueryResult;
27  
28  import org.apache.commons.logging.Log;
29  import org.apache.commons.logging.LogFactory;
30  import org.argeo.eclipse.ui.EclipseJcrMonitor;
31  import org.argeo.jcr.JcrMonitor;
32  import org.argeo.jcr.JcrUtils;
33  import org.argeo.node.security.Keyring;
34  import org.argeo.slc.SlcException;
35  import org.argeo.slc.client.ui.dist.DistPlugin;
36  import org.argeo.slc.repo.RepoUtils;
37  import org.eclipse.core.commands.AbstractHandler;
38  import org.eclipse.core.commands.ExecutionEvent;
39  import org.eclipse.core.commands.ExecutionException;
40  import org.eclipse.core.runtime.IProgressMonitor;
41  import org.eclipse.core.runtime.IStatus;
42  import org.eclipse.core.runtime.Status;
43  import org.eclipse.core.runtime.jobs.Job;
44  
45  /** Merge two workspaces */
46  public class MergeWorkspaces extends AbstractHandler {
47  	private final static Log log = LogFactory.getLog(MergeWorkspaces.class);
48  
49  	public final static String ID = DistPlugin.PLUGIN_ID + ".mergeWorkspaces";
50  	public final static String DEFAULT_LABEL = "Merge";
51  
52  	public final static String PARAM_SOURCE_WORKSPACE_NAME = "srcWkspName";
53  	public final static String PARAM_SOURCE_REPO_PATH = "srcRepoPath";
54  	public final static String PARAM_TARGET_WORKSPACE_NAME = "targetWkspName";
55  	public final static String PARAM_TARGET_REPO_PATH = "targetRepoPath";
56  
57  	// DEPENDENCY INJECTION
58  	private RepositoryFactory repositoryFactory;
59  	private Keyring keyring;
60  	private Repository nodeRepository;
61  
62  	public Object execute(ExecutionEvent event) throws ExecutionException {
63  		String targetRepoPath = event.getParameter(PARAM_TARGET_REPO_PATH);
64  		String targetWkspName = event.getParameter(PARAM_TARGET_WORKSPACE_NAME);
65  		String sourceRepoPath = event.getParameter(PARAM_SOURCE_REPO_PATH);
66  		String sourceWkspName = event.getParameter(PARAM_SOURCE_WORKSPACE_NAME);
67  
68  		Session nodeSession = null;
69  		try {
70  			nodeSession = nodeRepository.login();
71  			Node srcRepoNode = nodeSession.getNode(sourceRepoPath);
72  			Repository srcRepository = RepoUtils.getRepository(repositoryFactory, keyring, srcRepoNode);
73  			Credentials srcCredentials = RepoUtils.getRepositoryCredentials(keyring, srcRepoNode);
74  
75  			Node targetRepoNode = nodeSession.getNode(targetRepoPath);
76  			Repository targetRepository = RepoUtils.getRepository(repositoryFactory, keyring, targetRepoNode);
77  			Credentials targetCredentials = RepoUtils.getRepositoryCredentials(keyring, targetRepoNode);
78  
79  			// String msg = "Are you sure you want to merge distribution ["
80  			// + sourceWkspName + "] in distribution [" + targetWkspName
81  			// + "] ?";
82  			//
83  			// boolean result = MessageDialog.openConfirm(
84  			// HandlerUtil.getActiveShell(event), "Confirm Merge", msg);
85  
86  			// if (result) {
87  			// Open sessions here since the background thread
88  			// won't necessarily be authenticated.
89  			// Job should close the sessions.
90  			Session sourceSession = srcRepository.login(srcCredentials, sourceWkspName);
91  			Session targetSession;
92  			try {
93  				targetSession = targetRepository.login(targetCredentials, targetWkspName);
94  			} catch (NoSuchWorkspaceException e) {
95  				Session defaultSession = targetRepository.login(targetCredentials);
96  				try {
97  					defaultSession.getWorkspace().createWorkspace(targetWkspName);
98  				} catch (Exception e1) {
99  					throw new SlcException("Cannot create new workspace " + targetWkspName, e);
100 				} finally {
101 					JcrUtils.logoutQuietly(defaultSession);
102 				}
103 				targetSession = targetRepository.login(targetCredentials, targetWkspName);
104 			}
105 
106 			Job workspaceMergeJob = new WorkspaceMergeJob(sourceSession, targetSession);
107 			workspaceMergeJob.setUser(true);
108 			workspaceMergeJob.schedule();
109 		} catch (RepositoryException re) {
110 			throw new SlcException("Unexpected error while merging workspaces.", re);
111 		} finally {
112 			JcrUtils.logoutQuietly(nodeSession);
113 		}
114 		return null;
115 	}
116 
117 	private static class WorkspaceMergeJob extends Job {
118 		private Session sourceSession;
119 		private Session targetSession;
120 
121 		public WorkspaceMergeJob(Session sourceSession, Session targetSession) {
122 			super("Workspace merge");
123 			this.sourceSession = sourceSession;
124 			this.targetSession = targetSession;
125 		}
126 
127 		@Override
128 		protected IStatus run(IProgressMonitor eclipseMonitor) {
129 			long begin = System.currentTimeMillis();
130 			try {
131 				Query countQuery = sourceSession.getWorkspace().getQueryManager()
132 						.createQuery("select file from [nt:file] as file", Query.JCR_SQL2);
133 				QueryResult result = countQuery.execute();
134 				Long expectedCount = result.getNodes().getSize();
135 				if (log.isDebugEnabled())
136 					log.debug("Will copy " + expectedCount + " files...");
137 
138 				JcrMonitor monitor = new EclipseJcrMonitor(eclipseMonitor);
139 				eclipseMonitor.beginTask("Copy files", expectedCount.intValue());
140 
141 				Long count = JcrUtils.copyFiles(sourceSession.getRootNode(), targetSession.getRootNode(), true, monitor,
142 						true);
143 
144 				monitor.done();
145 				long duration = (System.currentTimeMillis() - begin) / 1000;// in
146 																			// s
147 				if (log.isDebugEnabled())
148 					log.debug("Copied " + count + " files in " + (duration / 60) + "min " + (duration % 60) + "s");
149 
150 				return Status.OK_STATUS;
151 			} catch (RepositoryException e) {
152 				return new Status(IStatus.ERROR, DistPlugin.PLUGIN_ID, "Cannot merge", e);
153 			} finally {
154 				JcrUtils.logoutQuietly(sourceSession);
155 				JcrUtils.logoutQuietly(targetSession);
156 			}
157 		}
158 	}
159 
160 	/* DEPENDENCY INJECTION */
161 	public void setNodeRepository(Repository nodeRepository) {
162 		this.nodeRepository = nodeRepository;
163 	}
164 
165 	public void setRepositoryFactory(RepositoryFactory repositoryFactory) {
166 		this.repositoryFactory = repositoryFactory;
167 	}
168 
169 	public void setKeyring(Keyring keyring) {
170 		this.keyring = keyring;
171 	}
172 }