1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.modeshape.connector.svn;
25
26 import java.util.Hashtable;
27 import java.util.List;
28 import java.util.Map;
29 import javax.naming.Context;
30 import javax.naming.Name;
31 import javax.naming.Reference;
32 import javax.naming.StringRefAddr;
33 import javax.naming.spi.ObjectFactory;
34 import net.jcip.annotations.ThreadSafe;
35 import org.modeshape.common.i18n.I18n;
36 import org.modeshape.common.util.CheckArg;
37 import org.modeshape.common.util.StringUtil;
38 import org.modeshape.connector.svn.SvnRepository.SvnTransaction;
39 import org.modeshape.graph.ExecutionContext;
40 import org.modeshape.graph.connector.RepositoryConnection;
41 import org.modeshape.graph.connector.RepositorySource;
42 import org.modeshape.graph.connector.RepositorySourceCapabilities;
43 import org.modeshape.graph.connector.RepositorySourceException;
44 import org.modeshape.graph.connector.base.AbstractRepositorySource;
45 import org.modeshape.graph.connector.base.Connection;
46 import org.modeshape.graph.connector.base.PathNode;
47 import org.modeshape.graph.request.CreateWorkspaceRequest.CreateConflictBehavior;
48
49
50
51
52
53
54
55 @ThreadSafe
56 public class SvnRepositorySource extends AbstractRepositorySource implements ObjectFactory {
57
58
59
60
61 private static final long serialVersionUID = 1L;
62
63 protected static final String SOURCE_NAME = "sourceName";
64 protected static final String SVN_REPOSITORY_ROOT_URL = "repositoryRootURL";
65 protected static final String SVN_USERNAME = "username";
66 protected static final String SVN_PASSWORD = "password";
67 protected static final String RETRY_LIMIT = "retryLimit";
68 protected static final String ROOT_NODE_UUID = "rootNodeUuid";
69 protected static final String DEFAULT_WORKSPACE = "defaultWorkspace";
70 protected static final String PREDEFINED_WORKSPACE_NAMES = "predefinedWorkspaceNames";
71 protected static final String ALLOW_CREATING_WORKSPACES = "allowCreatingWorkspaces";
72
73
74
75
76 protected static final boolean SUPPORTS_EVENTS = true;
77
78
79
80 protected static final boolean SUPPORTS_SAME_NAME_SIBLINGS = false;
81
82
83
84 protected static final boolean DEFAULT_SUPPORTS_CREATING_WORKSPACES = true;
85
86
87
88 public static final boolean DEFAULT_SUPPORTS_UPDATES = false;
89
90
91
92
93 protected static final boolean SUPPORTS_REFERENCES = false;
94
95 private volatile String repositoryRootUrl;
96 private volatile String username;
97 private volatile String password;
98 private volatile String defaultWorkspace;
99 private volatile String[] predefinedWorkspaces = new String[] {};
100 private volatile RepositorySourceCapabilities capabilities = new RepositorySourceCapabilities(
101 SUPPORTS_SAME_NAME_SIBLINGS,
102 DEFAULT_SUPPORTS_UPDATES,
103 SUPPORTS_EVENTS,
104 DEFAULT_SUPPORTS_CREATING_WORKSPACES,
105 SUPPORTS_REFERENCES);
106
107 private transient SvnRepository repository;
108
109 private ExecutionContext defaultContext = new ExecutionContext();
110
111
112
113
114 public SvnRepositorySource() {
115 }
116
117
118
119
120
121
122 public RepositorySourceCapabilities getCapabilities() {
123 return capabilities;
124 }
125
126
127
128
129 public String getRepositoryRootUrl() {
130 return this.repositoryRootUrl;
131 }
132
133
134
135
136
137
138
139 public synchronized void setRepositoryRootUrl( String url ) {
140 CheckArg.isNotEmpty(url, "RepositoryRootUrl");
141 this.repositoryRootUrl = url;
142 }
143
144 public String getUsername() {
145 return this.username;
146 }
147
148
149
150
151 public synchronized void setUsername( String username ) {
152 this.username = username;
153 }
154
155 public String getPassword() {
156 return this.password;
157 }
158
159
160
161
162 public synchronized void setPassword( String password ) {
163 this.password = password;
164 }
165
166
167
168
169
170
171 public boolean getSupportsUpdates() {
172 return capabilities.supportsUpdates();
173 }
174
175
176
177
178
179
180
181
182
183
184 public String getDefaultWorkspaceName() {
185 return defaultWorkspace;
186 }
187
188
189
190
191
192
193
194
195
196
197 public synchronized void setDefaultWorkspaceName( String pathToDirectoryForDefaultWorkspace ) {
198 this.defaultWorkspace = pathToDirectoryForDefaultWorkspace;
199 }
200
201
202
203
204
205
206
207
208
209 public synchronized String[] getPredefinedWorkspaceNames() {
210 String[] copy = new String[predefinedWorkspaces.length];
211 System.arraycopy(predefinedWorkspaces, 0, copy, 0, predefinedWorkspaces.length);
212 return copy;
213 }
214
215
216
217
218
219
220
221
222
223
224 public synchronized void setPredefinedWorkspaceNames( String[] predefinedWorkspaceNames ) {
225 this.predefinedWorkspaces = predefinedWorkspaceNames;
226 }
227
228
229
230
231
232
233
234
235
236 public boolean isCreatingWorkspacesAllowed() {
237 return capabilities.supportsCreatingWorkspaces();
238 }
239
240
241
242
243
244
245
246
247
248
249 public synchronized void setCreatingWorkspacesAllowed( boolean allowWorkspaceCreation ) {
250 capabilities = new RepositorySourceCapabilities(capabilities.supportsSameNameSiblings(), capabilities.supportsUpdates(),
251 capabilities.supportsEvents(), allowWorkspaceCreation,
252 capabilities.supportsReferences());
253 }
254
255
256
257
258
259
260
261 @Override
262 public boolean areUpdatesAllowed() {
263 return capabilities.supportsUpdates();
264 }
265
266
267
268
269
270
271
272
273 public synchronized void setUpdatesAllowed( boolean allowUpdates ) {
274 capabilities = new RepositorySourceCapabilities(capabilities.supportsSameNameSiblings(), allowUpdates,
275 capabilities.supportsEvents(), capabilities.supportsCreatingWorkspaces(),
276 capabilities.supportsReferences());
277 }
278
279
280
281
282 @Override
283 public boolean equals( Object obj ) {
284 if (obj == this) return true;
285 if (obj instanceof SvnRepositorySource) {
286 SvnRepositorySource that = (SvnRepositorySource)obj;
287 if (this.getName() == null) {
288 if (that.getName() != null) return false;
289 } else {
290 if (!this.getName().equals(that.getName())) return false;
291 }
292 return true;
293 }
294 return false;
295 }
296
297 @Override
298 public int hashCode() {
299 return getName().hashCode();
300 }
301
302
303
304
305
306
307 public synchronized Reference getReference() {
308 String className = getClass().getName();
309 String factoryClassName = this.getClass().getName();
310 Reference ref = new Reference(className, factoryClassName, null);
311
312 if (getName() != null) {
313 ref.add(new StringRefAddr(SOURCE_NAME, getName()));
314 }
315 if (getRepositoryRootUrl() != null) {
316 ref.add(new StringRefAddr(SVN_REPOSITORY_ROOT_URL, getRepositoryRootUrl()));
317 }
318 if (getUsername() != null) {
319 ref.add(new StringRefAddr(SVN_USERNAME, getUsername()));
320 }
321 if (getPassword() != null) {
322 ref.add(new StringRefAddr(SVN_PASSWORD, getPassword()));
323 }
324 ref.add(new StringRefAddr(RETRY_LIMIT, Integer.toString(getRetryLimit())));
325 ref.add(new StringRefAddr(ROOT_NODE_UUID, getRootNodeUuidObject().toString()));
326 ref.add(new StringRefAddr(DEFAULT_WORKSPACE, getDefaultWorkspaceName()));
327 ref.add(new StringRefAddr(ALLOW_CREATING_WORKSPACES, Boolean.toString(isCreatingWorkspacesAllowed())));
328 String[] workspaceNames = getPredefinedWorkspaceNames();
329 if (workspaceNames != null && workspaceNames.length != 0) {
330 ref.add(new StringRefAddr(PREDEFINED_WORKSPACE_NAMES, StringUtil.combineLines(workspaceNames)));
331 }
332 return ref;
333
334 }
335
336
337
338
339
340
341
342 public Object getObjectInstance( Object obj,
343 Name name,
344 Context nameCtx,
345 Hashtable<?, ?> environment ) throws Exception {
346 if (!(obj instanceof Reference)) return null;
347
348 Map<String, Object> values = valuesFrom((Reference)obj);
349
350 String sourceName = (String)values.get(SOURCE_NAME);
351 String repositoryRootUrl = (String)values.get(SVN_REPOSITORY_ROOT_URL);
352 String username = (String)values.get(SVN_USERNAME);
353 String password = (String)values.get(SVN_PASSWORD);
354 String retryLimit = (String)values.get(RETRY_LIMIT);
355 String rootNodeUuid = (String)values.get(ROOT_NODE_UUID);
356 String defaultWorkspace = (String)values.get(DEFAULT_WORKSPACE);
357 String createWorkspaces = (String)values.get(ALLOW_CREATING_WORKSPACES);
358
359 String combinedWorkspaceNames = (String)values.get(PREDEFINED_WORKSPACE_NAMES);
360 String[] workspaceNames = null;
361 if (combinedWorkspaceNames != null) {
362 List<String> paths = StringUtil.splitLines(combinedWorkspaceNames);
363 workspaceNames = paths.toArray(new String[paths.size()]);
364 }
365
366 SvnRepositorySource source = new SvnRepositorySource();
367 if (sourceName != null) source.setName(sourceName);
368 if (repositoryRootUrl != null && repositoryRootUrl.length() > 0) source.setRepositoryRootUrl(repositoryRootUrl);
369 if (username != null) source.setUsername(username);
370 if (password != null) source.setPassword(password);
371 if (retryLimit != null) source.setRetryLimit(Integer.parseInt(retryLimit));
372 if (rootNodeUuid != null) source.setRootNodeUuidObject(rootNodeUuid);
373 if (defaultWorkspace != null) source.setDefaultWorkspaceName(defaultWorkspace);
374 if (createWorkspaces != null) source.setCreatingWorkspacesAllowed(Boolean.parseBoolean(createWorkspaces));
375 if (workspaceNames != null && workspaceNames.length != 0) source.setPredefinedWorkspaceNames(workspaceNames);
376 return source;
377 }
378
379
380
381
382
383
384 public synchronized RepositoryConnection getConnection() throws RepositorySourceException {
385
386 String sourceName = getName();
387 if (sourceName == null || sourceName.trim().length() == 0) {
388 I18n msg = SvnRepositoryConnectorI18n.propertyIsRequired;
389 throw new RepositorySourceException(getName(), msg.text("name"));
390 }
391
392 String sourceUsername = getUsername();
393 if (sourceUsername == null || sourceUsername.trim().length() == 0) {
394 I18n msg = SvnRepositoryConnectorI18n.propertyIsRequired;
395 throw new RepositorySourceException(getUsername(), msg.text("username"));
396 }
397
398 String sourcePassword = getPassword();
399 if (sourcePassword == null) {
400 I18n msg = SvnRepositoryConnectorI18n.propertyIsRequired;
401 throw new RepositorySourceException(getPassword(), msg.text("password"));
402 }
403
404 String repositoryRootURL = getRepositoryRootUrl();
405 if (repositoryRootURL == null || repositoryRootURL.trim().length() == 0) {
406 I18n msg = SvnRepositoryConnectorI18n.propertyIsRequired;
407 throw new RepositorySourceException(getRepositoryRootUrl(), msg.text("repositoryRootURL"));
408 }
409 repositoryRootURL = repositoryRootURL.trim();
410 if (repositoryRootURL.endsWith("/")) repositoryRootURL = repositoryRootURL + "/";
411
412 if (repository == null) {
413 repository = new SvnRepository(this);
414
415 ExecutionContext context = repositoryContext != null ? repositoryContext.getExecutionContext() : defaultContext;
416 SvnTransaction txn = repository.startTransaction(context, false);
417 try {
418
419 for (String initialName : getPredefinedWorkspaceNames()) {
420 repository.createWorkspace(txn, initialName, CreateConflictBehavior.DO_NOT_CREATE, null);
421 }
422 } finally {
423 txn.commit();
424 }
425
426 }
427 return new Connection<PathNode, SvnWorkspace>(this, repository);
428 }
429 }