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.Node;
20  import javax.jcr.Repository;
21  import javax.jcr.RepositoryException;
22  import javax.jcr.RepositoryFactory;
23  import javax.jcr.Session;
24  import javax.jcr.security.Privilege;
25  
26  import org.apache.commons.logging.Log;
27  import org.apache.commons.logging.LogFactory;
28  import org.argeo.cms.ui.workbench.util.PrivilegedJob;
29  import org.argeo.eclipse.ui.EclipseJcrMonitor;
30  import org.argeo.jcr.JcrMonitor;
31  import org.argeo.jcr.JcrUtils;
32  import org.argeo.node.security.Keyring;
33  import org.argeo.slc.SlcConstants;
34  import org.argeo.slc.SlcException;
35  import org.argeo.slc.client.ui.dist.DistPlugin;
36  import org.argeo.slc.client.ui.dist.utils.CommandHelpers;
37  import org.argeo.slc.repo.RepoUtils;
38  import org.eclipse.core.commands.AbstractHandler;
39  import org.eclipse.core.commands.ExecutionEvent;
40  import org.eclipse.core.commands.ExecutionException;
41  import org.eclipse.core.runtime.IProgressMonitor;
42  import org.eclipse.core.runtime.IStatus;
43  import org.eclipse.core.runtime.Status;
44  import org.eclipse.core.runtime.jobs.Job;
45  import org.eclipse.jface.dialogs.ErrorDialog;
46  import org.eclipse.jface.dialogs.InputDialog;
47  import org.eclipse.jface.resource.ImageDescriptor;
48  import org.eclipse.jface.window.Window;
49  import org.eclipse.swt.widgets.Display;
50  import org.eclipse.ui.handlers.HandlerUtil;
51  
52  /** Create a copy of the chosen workspace in a remote repository */
53  public class CopyWorkspace extends AbstractHandler {
54  	private static final Log log = LogFactory.getLog(CopyWorkspace.class);
55  
56  	public final static String ID = DistPlugin.PLUGIN_ID + ".copyWorkspace";
57  	public final static String DEFAULT_LABEL = "Duplicate...";
58  	public final static ImageDescriptor DEFAULT_ICON = DistPlugin
59  			.getImageDescriptor("icons/addItem.gif");
60  
61  	public final static String PARAM_SOURCE_WORKSPACE_NAME = "srcWkspName";
62  	public final static String PARAM_TARGET_REPO_PATH = "targetRepoPath";
63  
64  	// DEPENDENCY INJECTION
65  	private RepositoryFactory repositoryFactory;
66  	private Keyring keyring;
67  	private Repository nodeRepository;
68  
69  	public Object execute(ExecutionEvent event) throws ExecutionException {
70  
71  		String targetRepoPath = event.getParameter(PARAM_TARGET_REPO_PATH);
72  		String wkspName = event.getParameter(PARAM_SOURCE_WORKSPACE_NAME);
73  
74  		InputDialog inputDialog = new InputDialog(HandlerUtil
75  				.getActiveWorkbenchWindow(event).getShell(),
76  				"New copy of workspace " + wkspName,
77  				"Choose a name for the workspace to create", "", null);
78  		int result = inputDialog.open();
79  		if (result == Window.OK) {
80  			String newWorkspaceName = inputDialog.getValue();
81  
82  			if (newWorkspaceName == null || newWorkspaceName.trim().equals("")
83  					|| newWorkspaceName.trim().equals(wkspName.trim())) {
84  				ErrorDialog
85  						.openError(HandlerUtil.getActiveShell(event),
86  								"Non valid workspace name", newWorkspaceName
87  										+ " is not a valid workspace name.",
88  								new Status(IStatus.ERROR, "not valid", 0,
89  										"Error", null));
90  				return null;
91  			}
92  			Job copyWkspJob = new CopyWkspJob(repositoryFactory, keyring,
93  					nodeRepository, targetRepoPath, wkspName, newWorkspaceName,
94  					HandlerUtil.getActiveWorkbenchWindow(event).getShell()
95  							.getDisplay());
96  			copyWkspJob.setUser(true);
97  			copyWkspJob.schedule();
98  		}
99  		return null;
100 	}
101 
102 	private static class CopyWkspJob extends PrivilegedJob {
103 
104 		private RepositoryFactory repositoryFactory;
105 		private Keyring keyring;
106 		private Repository localRepository;
107 		private String targetRepoPath;
108 		private String srcWkspName;
109 		private String targetWkspName;
110 		private Display display;
111 
112 		public CopyWkspJob(RepositoryFactory repositoryFactory,
113 				Keyring keyring, Repository localRepository,
114 				String targetRepoPath, String srcWkspName,
115 				String targetWkspName, Display display) {
116 			super("Duplicate workspace");
117 			this.repositoryFactory = repositoryFactory;
118 			this.keyring = keyring;
119 			this.localRepository = localRepository;
120 			this.targetRepoPath = targetRepoPath;
121 			this.srcWkspName = srcWkspName;
122 			this.targetWkspName = targetWkspName;
123 			this.display = display;
124 		}
125 
126 		@Override
127 		protected IStatus doRun(IProgressMonitor progressMonitor) {
128 			long begin = System.currentTimeMillis();
129 
130 			JcrMonitor monitor = new EclipseJcrMonitor(progressMonitor);
131 			monitor.beginTask("Copy workspace", -1);
132 			monitor.subTask("Copying nodes");
133 
134 			Session nodeSession = null;
135 			Session srcSession = null;
136 			Session newSession = null;
137 			try {
138 				nodeSession = localRepository.login();
139 				Node repoNode = nodeSession.getNode(targetRepoPath);
140 				Repository repository = RepoUtils.getRepository(
141 						repositoryFactory, keyring, repoNode);
142 				Credentials credentials = RepoUtils.getRepositoryCredentials(
143 						keyring, repoNode);
144 
145 				srcSession = repository.login(credentials, srcWkspName);
146 
147 				// Create the workspace
148 				srcSession.getWorkspace().createWorkspace(targetWkspName);
149 				Node srcRootNode = srcSession.getRootNode();
150 				// log in the newly created workspace
151 				newSession = repository.login(credentials, targetWkspName);
152 				Node newRootNode = newSession.getRootNode();
153 				RepoUtils.copy(srcRootNode, newRootNode, monitor);
154 				newSession.save();
155 				JcrUtils.addPrivilege(newSession, "/", SlcConstants.ROLE_SLC,
156 						Privilege.JCR_ALL);
157 
158 				display.asyncExec(new Runnable() {
159 					public void run() {
160 						CommandHelpers.callCommand(RefreshDistributionsView.ID);
161 					}
162 				});
163 				monitor.worked(1);
164 
165 			} catch (RepositoryException re) {
166 				throw new SlcException(
167 						"Unexpected error while creating the new workspace.",
168 						re);
169 			} finally {
170 				JcrUtils.logoutQuietly(newSession);
171 				JcrUtils.logoutQuietly(srcSession);
172 				JcrUtils.logoutQuietly(nodeSession);
173 			}
174 
175 			monitor.done();
176 			long duration = (System.currentTimeMillis() - begin) / 1000;// in
177 																		// s
178 			if (log.isDebugEnabled())
179 				log.debug("Created workspace " + targetWkspName + " in "
180 						+ (duration / 60) + "min " + (duration % 60) + "s");
181 			return Status.OK_STATUS;
182 		}
183 
184 	}
185 
186 	/* DEPENDENCY INJECTION */
187 	public void setNodeRepository(Repository nodeRepository) {
188 		this.nodeRepository = nodeRepository;
189 	}
190 
191 	public void setRepositoryFactory(RepositoryFactory repositoryFactory) {
192 		this.repositoryFactory = repositoryFactory;
193 	}
194 
195 	public void setKeyring(Keyring keyring) {
196 		this.keyring = keyring;
197 	}
198 }