1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 package org.modeshape.connector.jcr;
26
27 import java.io.ByteArrayInputStream;
28 import java.io.ByteArrayOutputStream;
29 import java.io.IOException;
30 import java.io.ObjectInputStream;
31 import java.io.ObjectOutputStream;
32 import java.util.Enumeration;
33 import java.util.HashMap;
34 import java.util.Hashtable;
35 import java.util.Map;
36 import javax.jcr.Credentials;
37 import javax.jcr.Repository;
38 import javax.jcr.SimpleCredentials;
39 import javax.naming.BinaryRefAddr;
40 import javax.naming.Context;
41 import javax.naming.InitialContext;
42 import javax.naming.NamingException;
43 import javax.naming.RefAddr;
44 import javax.naming.Reference;
45 import javax.naming.StringRefAddr;
46 import javax.naming.spi.ObjectFactory;
47 import net.jcip.annotations.ThreadSafe;
48 import org.modeshape.common.i18n.I18n;
49 import org.modeshape.graph.cache.CachePolicy;
50 import org.modeshape.graph.connector.RepositoryConnection;
51 import org.modeshape.graph.connector.RepositoryContext;
52 import org.modeshape.graph.connector.RepositorySource;
53 import org.modeshape.graph.connector.RepositorySourceCapabilities;
54 import org.modeshape.graph.connector.RepositorySourceException;
55
56
57
58
59
60
61 @ThreadSafe
62 public class JcrRepositorySource implements RepositorySource, ObjectFactory {
63
64
65
66
67 private static final long serialVersionUID = 1L;
68
69 protected static final String SOURCE_NAME = "sourceName";
70 protected static final String REPOSITORY_JNDI_NAME = "repositoryJndiName";
71 protected static final String USERNAME = "username";
72 protected static final String PASSWORD = "password";
73 protected static final String CREDENTIALS = "credentials";
74 protected static final String DEFAULT_CACHE_POLICY = "defaultCachePolicy";
75 protected static final String RETRY_LIMIT = "retryLimit";
76
77
78
79
80 public static final int DEFAULT_RETRY_LIMIT = 0;
81
82
83
84
85 protected static final boolean SUPPORTS_EVENTS = true;
86
87
88
89 protected static final boolean SUPPORTS_SAME_NAME_SIBLINGS = true;
90
91
92
93 protected static final boolean SUPPORTS_UPDATES = true;
94
95
96
97 protected static final boolean SUPPORTS_CREATING_WORKSPACES = false;
98
99
100
101 protected static final boolean SUPPORTS_REFERENCES = false;
102
103 private volatile String name;
104 private volatile String repositoryJndiName;
105 private volatile String username;
106 private volatile String password;
107 private volatile Credentials credentials;
108 private volatile CachePolicy defaultCachePolicy;
109 private volatile int retryLimit = DEFAULT_RETRY_LIMIT;
110 private volatile RepositorySourceCapabilities capabilities = new RepositorySourceCapabilities(SUPPORTS_SAME_NAME_SIBLINGS,
111 SUPPORTS_UPDATES,
112 SUPPORTS_EVENTS,
113 SUPPORTS_CREATING_WORKSPACES,
114 SUPPORTS_REFERENCES);
115 private transient Repository repository;
116 private transient Context jndiContext;
117 private transient RepositoryContext repositoryContext;
118
119
120
121
122 public JcrRepositorySource() {
123 }
124
125
126
127
128
129
130 public String getName() {
131 return name;
132 }
133
134
135
136
137
138
139 public void setName( String name ) {
140 if (name != null) {
141 name = name.trim();
142 if (name.length() == 0) name = null;
143 }
144 this.name = name;
145 }
146
147
148
149
150
151
152 public RepositorySourceCapabilities getCapabilities() {
153 return capabilities;
154 }
155
156
157
158
159
160
161 public boolean getUpdatesAllowed() {
162 return capabilities.supportsUpdates();
163 }
164
165
166
167
168 public String getRepositoryJndiName() {
169 return repositoryJndiName;
170 }
171
172
173
174
175
176
177 public void setRepositoryJndiName( String repositoryJndiName ) {
178 if (repositoryJndiName != null && repositoryJndiName.trim().length() == 0) repositoryJndiName = null;
179 this.repositoryJndiName = repositoryJndiName;
180 }
181
182
183
184
185
186
187 public String getUsername() {
188 return username;
189 }
190
191
192
193
194 public synchronized void setUsername( String username ) {
195 this.username = username;
196 }
197
198
199
200
201 public String getPassword() {
202 return password;
203 }
204
205
206
207
208 public synchronized void setPassword( String password ) {
209 this.password = password;
210 }
211
212
213
214
215
216
217 public Credentials getCredentials() {
218 return credentials;
219 }
220
221
222
223
224
225
226 public void setCredentials( Credentials credentials ) {
227 this.credentials = credentials;
228 }
229
230
231
232
233
234
235 public CachePolicy getDefaultCachePolicy() {
236 return defaultCachePolicy;
237 }
238
239
240
241
242 public synchronized void setDefaultCachePolicy( CachePolicy defaultCachePolicy ) {
243 if (this.defaultCachePolicy == defaultCachePolicy || this.defaultCachePolicy != null
244 && this.defaultCachePolicy.equals(defaultCachePolicy)) return;
245 this.defaultCachePolicy = defaultCachePolicy;
246 }
247
248
249
250
251
252
253 public int getRetryLimit() {
254 return retryLimit;
255 }
256
257
258
259
260
261
262 public synchronized void setRetryLimit( int limit ) {
263 retryLimit = limit < 0 ? 0 : limit;
264 }
265
266
267
268
269
270
271 public void initialize( RepositoryContext context ) throws RepositorySourceException {
272 this.repositoryContext = context;
273 }
274
275 protected RepositoryContext getRepositoryContext() {
276 return repositoryContext;
277 }
278
279 protected synchronized Repository getRepository() {
280 return this.repository;
281 }
282
283 protected synchronized void setRepository( Repository repository ) {
284 this.repository = repository;
285 }
286
287 protected synchronized Context getContext() {
288 return this.jndiContext;
289 }
290
291 protected synchronized void setContext( Context context ) {
292 this.jndiContext = context;
293 }
294
295
296
297
298
299
300 public synchronized Reference getReference() {
301 String className = getClass().getName();
302 String factoryClassName = this.getClass().getName();
303 Reference ref = new Reference(className, factoryClassName, null);
304
305 if (getName() != null) {
306 ref.add(new StringRefAddr(SOURCE_NAME, getName()));
307 }
308 ref.add(new StringRefAddr(SOURCE_NAME, getName()));
309 ref.add(new StringRefAddr(REPOSITORY_JNDI_NAME, getRepositoryJndiName()));
310 ref.add(new StringRefAddr(USERNAME, getUsername()));
311 ref.add(new StringRefAddr(PASSWORD, getPassword()));
312 ref.add(new StringRefAddr(RETRY_LIMIT, Integer.toString(getRetryLimit())));
313 if (getCredentials() != null) {
314 ByteArrayOutputStream baos = new ByteArrayOutputStream();
315 Credentials credentials = getCredentials();
316 try {
317 ObjectOutputStream oos = new ObjectOutputStream(baos);
318 oos.writeObject(credentials);
319 ref.add(new BinaryRefAddr(CREDENTIALS, baos.toByteArray()));
320 } catch (IOException e) {
321 I18n msg = JcrConnectorI18n.errorSerializingObjectUsedInSource;
322 throw new RepositorySourceException(getName(), msg.text(credentials.getClass().getName(), getName()), e);
323 }
324 }
325 if (getDefaultCachePolicy() != null) {
326 ByteArrayOutputStream baos = new ByteArrayOutputStream();
327 CachePolicy policy = getDefaultCachePolicy();
328 try {
329 ObjectOutputStream oos = new ObjectOutputStream(baos);
330 oos.writeObject(policy);
331 ref.add(new BinaryRefAddr(DEFAULT_CACHE_POLICY, baos.toByteArray()));
332 } catch (IOException e) {
333 I18n msg = JcrConnectorI18n.errorSerializingObjectUsedInSource;
334 throw new RepositorySourceException(getName(), msg.text(policy.getClass().getName(), getName()), e);
335 }
336 }
337 return ref;
338 }
339
340
341
342
343 public Object getObjectInstance( Object obj,
344 javax.naming.Name name,
345 Context nameCtx,
346 Hashtable<?, ?> environment ) throws Exception {
347 if (obj instanceof Reference) {
348 Map<String, Object> values = new HashMap<String, Object>();
349 Reference ref = (Reference)obj;
350 Enumeration<?> en = ref.getAll();
351 while (en.hasMoreElements()) {
352 RefAddr subref = (RefAddr)en.nextElement();
353 if (subref instanceof StringRefAddr) {
354 String key = subref.getType();
355 Object value = subref.getContent();
356 if (value != null) values.put(key, value.toString());
357 } else if (subref instanceof BinaryRefAddr) {
358 String key = subref.getType();
359 Object value = subref.getContent();
360 if (value instanceof byte[]) {
361
362 ByteArrayInputStream bais = new ByteArrayInputStream((byte[])value);
363 ObjectInputStream ois = new ObjectInputStream(bais);
364 value = ois.readObject();
365 values.put(key, value);
366 }
367 }
368 }
369 String sourceName = (String)values.get(SOURCE_NAME);
370 String repositoryJndiName = (String)values.get(REPOSITORY_JNDI_NAME);
371 String username = (String)values.get(USERNAME);
372 String password = (String)values.get(PASSWORD);
373 String retryLimit = (String)values.get(RETRY_LIMIT);
374 Object credentials = values.get(CREDENTIALS);
375 Object defaultCachePolicy = values.get(DEFAULT_CACHE_POLICY);
376
377
378 JcrRepositorySource source = new JcrRepositorySource();
379 if (sourceName != null) source.setName(sourceName);
380 if (repositoryJndiName != null) source.setRepositoryJndiName(repositoryJndiName);
381 if (username != null) source.setUsername(username);
382 if (password != null) source.setPassword(password);
383 if (retryLimit != null) source.setRetryLimit(Integer.parseInt(retryLimit));
384 if (credentials instanceof Credentials) {
385 source.setCredentials((Credentials)credentials);
386 }
387 if (defaultCachePolicy instanceof CachePolicy) {
388 source.setDefaultCachePolicy((CachePolicy)defaultCachePolicy);
389 }
390 return source;
391 }
392 return null;
393 }
394
395
396
397
398
399
400 public synchronized RepositoryConnection getConnection() throws RepositorySourceException {
401 if (name == null || name.trim().length() == 0) {
402 I18n msg = JcrConnectorI18n.propertyIsRequired;
403 throw new RepositorySourceException(name, msg.text("name"));
404 }
405 if (repositoryJndiName == null || repositoryJndiName.trim().length() == 0) {
406 I18n msg = JcrConnectorI18n.propertyIsRequired;
407 throw new RepositorySourceException(getName(), msg.text("repositoryJndiName"));
408 }
409 if (this.repository == null) {
410 Context context = getContext();
411 if (context == null) {
412 try {
413 context = new InitialContext();
414 } catch (NamingException err) {
415 throw new RepositorySourceException(name, err);
416 }
417 }
418
419
420 Repository repository = null;
421 Object object = null;
422 try {
423 object = context.lookup(repositoryJndiName);
424 if (object != null) repository = (Repository)object;
425 } catch (ClassCastException err) {
426 I18n msg = JcrConnectorI18n.objectFoundInJndiWasNotRepository;
427 String className = object != null ? object.getClass().getName() : "null";
428 throw new RepositorySourceException(getName(), msg.text(repositoryJndiName, this.getName(), className), err);
429 } catch (Throwable err) {
430 if (err instanceof RuntimeException) throw (RuntimeException)err;
431 throw new RepositorySourceException(getName(), err);
432 }
433 if (repository == null) {
434 I18n msg = JcrConnectorI18n.repositoryObjectNotFoundInJndi;
435 throw new RepositorySourceException(getName(), msg.text(repositoryJndiName));
436 }
437 this.repository = repository;
438 }
439 assert this.repository != null;
440
441
442 Credentials credentials = getCredentials();
443 if (credentials == null || (username != null || password != null)) {
444 char[] passwd = this.password != null ? password.toCharArray() : new char[] {};
445 credentials = new SimpleCredentials(username, passwd);
446 }
447
448
449 return new JcrRepositoryConnection(this, repository, credentials);
450 }
451
452
453
454
455
456
457 public void close() {
458
459 this.repositoryContext = null;
460 this.repository = null;
461 }
462 }