001 /*
002 * JBoss DNA (http://www.jboss.org/dna)
003 * See the COPYRIGHT.txt file distributed with this work for information
004 * regarding copyright ownership. Some portions may be licensed
005 * to Red Hat, Inc. under one or more contributor license agreements.
006 * See the AUTHORS.txt file in the distribution for a full listing of
007 * individual contributors.
008 *
009 * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
010 * is licensed to you under the terms of the GNU Lesser General Public License as
011 * published by the Free Software Foundation; either version 2.1 of
012 * the License, or (at your option) any later version.
013 *
014 * JBoss DNA is distributed in the hope that it will be useful,
015 * but WITHOUT ANY WARRANTY; without even the implied warranty of
016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017 * Lesser General Public License for more details.
018 *
019 * You should have received a copy of the GNU Lesser General Public
020 * License along with this software; if not, write to the Free
021 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
022 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
023 */
024 package org.jboss.dna.connector.jbosscache;
025
026 import java.io.ByteArrayInputStream;
027 import java.io.ByteArrayOutputStream;
028 import java.io.IOException;
029 import java.io.ObjectInputStream;
030 import java.io.ObjectOutputStream;
031 import java.util.Enumeration;
032 import java.util.HashMap;
033 import java.util.HashSet;
034 import java.util.Hashtable;
035 import java.util.List;
036 import java.util.Map;
037 import java.util.Set;
038 import java.util.UUID;
039 import javax.naming.BinaryRefAddr;
040 import javax.naming.Context;
041 import javax.naming.InitialContext;
042 import javax.naming.NamingException;
043 import javax.naming.RefAddr;
044 import javax.naming.Reference;
045 import javax.naming.Referenceable;
046 import javax.naming.StringRefAddr;
047 import javax.naming.spi.ObjectFactory;
048 import net.jcip.annotations.ThreadSafe;
049 import org.jboss.cache.Cache;
050 import org.jboss.cache.CacheFactory;
051 import org.jboss.cache.DefaultCacheFactory;
052 import org.jboss.dna.common.i18n.I18n;
053 import org.jboss.dna.common.util.StringUtil;
054 import org.jboss.dna.graph.DnaLexicon;
055 import org.jboss.dna.graph.cache.CachePolicy;
056 import org.jboss.dna.graph.connector.RepositoryConnection;
057 import org.jboss.dna.graph.connector.RepositoryContext;
058 import org.jboss.dna.graph.connector.RepositorySource;
059 import org.jboss.dna.graph.connector.RepositorySourceCapabilities;
060 import org.jboss.dna.graph.connector.RepositorySourceException;
061 import org.jboss.dna.graph.observe.Observer;
062 import org.jboss.dna.graph.property.Name;
063
064 /**
065 * A repository source that uses a JBoss Cache instance to manage the content. This source is capable of using an existing
066 * {@link Cache} instance or creating a new instance. This process is controlled entirely by the JavaBean properties of the
067 * JBossCacheSource instance.
068 * <p>
069 * This source first attempts to find an existing cache in {@link #getCacheJndiName() JNDI}. If none is found, then it attempts to
070 * create a cache instance using the {@link CacheFactory} found in {@link #getCacheFactoryJndiName() JNDI} (or the
071 * {@link DefaultCacheFactory} if no such factory is available) and the {@link #getCacheConfigurationName() cache configuration
072 * name} if supplied or the default configuration if not set.
073 * </p>
074 * <p>
075 * Like other {@link RepositorySource} classes, instances of JBossCacheSource can be placed into JNDI and do support the creation
076 * of {@link Referenceable JNDI referenceable} objects and resolution of references into JBossCacheSource.
077 * </p>
078 *
079 * @author Randall Hauch
080 */
081 @ThreadSafe
082 public class JBossCacheSource implements RepositorySource, ObjectFactory {
083
084 private static final long serialVersionUID = 2L;
085 /**
086 * The default limit is {@value} for retrying {@link RepositoryConnection connection} calls to the underlying source.
087 */
088 public static final int DEFAULT_RETRY_LIMIT = 0;
089 public static final String DEFAULT_UUID_PROPERTY_NAME = DnaLexicon.UUID.getString();
090
091 /**
092 * The initial {@link #getNameOfDefaultWorkspace() name of the default workspace} is "{@value} ", unless otherwise specified.
093 */
094 public static final String DEFAULT_NAME_OF_DEFAULT_WORKSPACE = "default";
095
096 protected static final String ROOT_NODE_UUID = "rootNodeUuid";
097 protected static final String SOURCE_NAME = "sourceName";
098 protected static final String DEFAULT_CACHE_POLICY = "defaultCachePolicy";
099 protected static final String CACHE_CONFIGURATION_NAME = "cacheConfigurationName";
100 protected static final String CACHE_FACTORY_JNDI_NAME = "cacheFactoryJndiName";
101 protected static final String CACHE_JNDI_NAME = "cacheJndiName";
102 protected static final String RETRY_LIMIT = "retryLimit";
103 protected static final String DEFAULT_WORKSPACE = "defaultWorkspace";
104 protected static final String PREDEFINED_WORKSPACE_NAMES = "predefinedWorkspaceNames";
105 protected static final String ALLOW_CREATING_WORKSPACES = "allowCreatingWorkspaces";
106
107 private volatile String name;
108 private volatile UUID rootNodeUuid = UUID.randomUUID();
109 private volatile CachePolicy defaultCachePolicy;
110 private volatile String cacheConfigurationName;
111 private volatile String cacheFactoryJndiName;
112 private volatile String cacheJndiName;
113 private volatile int retryLimit = DEFAULT_RETRY_LIMIT;
114 private volatile String defaultWorkspace;
115 private volatile String[] predefinedWorkspaces = new String[] {};
116 private volatile RepositorySourceCapabilities capabilities = new RepositorySourceCapabilities(true, true, false, true, false);
117 private transient JBossCacheWorkspaces workspaces;
118 private transient Context jndiContext;
119 private transient RepositoryContext repositoryContext;
120
121 /**
122 * Create a repository source instance.
123 */
124 public JBossCacheSource() {
125 }
126
127 /**
128 * {@inheritDoc}
129 *
130 * @see org.jboss.dna.graph.connector.RepositorySource#initialize(org.jboss.dna.graph.connector.RepositoryContext)
131 */
132 public void initialize( RepositoryContext context ) throws RepositorySourceException {
133 this.repositoryContext = context;
134 }
135
136 /**
137 * {@inheritDoc}
138 */
139 public String getName() {
140 return this.name;
141 }
142
143 /**
144 * {@inheritDoc}
145 *
146 * @see org.jboss.dna.graph.connector.RepositorySource#getCapabilities()
147 */
148 public RepositorySourceCapabilities getCapabilities() {
149 return capabilities;
150 }
151
152 /**
153 * {@inheritDoc}
154 *
155 * @see org.jboss.dna.graph.connector.RepositorySource#getRetryLimit()
156 */
157 public int getRetryLimit() {
158 return retryLimit;
159 }
160
161 /**
162 * {@inheritDoc}
163 *
164 * @see org.jboss.dna.graph.connector.RepositorySource#setRetryLimit(int)
165 */
166 public synchronized void setRetryLimit( int limit ) {
167 retryLimit = limit < 0 ? 0 : limit;
168 }
169
170 /**
171 * Set the name of this source
172 *
173 * @param name the name for this source
174 */
175 public synchronized void setName( String name ) {
176 if (this.name == name || this.name != null && this.name.equals(name)) return; // unchanged
177 this.name = name;
178 }
179
180 /**
181 * Get the default cache policy for this source, or null if the global default cache policy should be used
182 *
183 * @return the default cache policy, or null if this source has no explicit default cache policy
184 */
185 public CachePolicy getDefaultCachePolicy() {
186 return defaultCachePolicy;
187 }
188
189 /**
190 * @param defaultCachePolicy Sets defaultCachePolicy to the specified value.
191 */
192 public synchronized void setDefaultCachePolicy( CachePolicy defaultCachePolicy ) {
193 if (this.defaultCachePolicy == defaultCachePolicy || this.defaultCachePolicy != null
194 && this.defaultCachePolicy.equals(defaultCachePolicy)) return; // unchanged
195 this.defaultCachePolicy = defaultCachePolicy;
196 }
197
198 /**
199 * Get the name in JNDI of a {@link Cache} instance that should be used by this source.
200 * <p>
201 * This source first attempts to find an existing cache in {@link #getCacheJndiName() JNDI}. If none is found, then it
202 * attempts to create a cache instance using the {@link CacheFactory} found in {@link #getCacheFactoryJndiName() JNDI} (or the
203 * {@link DefaultCacheFactory} if no such factory is available) and the {@link #getCacheConfigurationName() cache
204 * configuration name} if supplied or the default configuration if not set.
205 * </p>
206 *
207 * @return the JNDI name of the {@link Cache} instance that should be used, or null if the cache is to be created with a cache
208 * factory {@link #getCacheFactoryJndiName() found in JNDI} using the specified {@link #getCacheConfigurationName()
209 * cache configuration name}.
210 * @see #setCacheJndiName(String)
211 * @see #getCacheConfigurationName()
212 * @see #getCacheFactoryJndiName()
213 */
214 public String getCacheJndiName() {
215 return cacheJndiName;
216 }
217
218 /**
219 * Set the name in JNDI of a {@link Cache} instance that should be used by this source.
220 * <p>
221 * This source first attempts to find an existing cache in {@link #getCacheJndiName() JNDI}. If none is found, then it
222 * attempts to create a cache instance using the {@link CacheFactory} found in {@link #getCacheFactoryJndiName() JNDI} (or the
223 * {@link DefaultCacheFactory} if no such factory is available) and the {@link #getCacheConfigurationName() cache
224 * configuration name} if supplied or the default configuration if not set.
225 * </p>
226 *
227 * @param cacheJndiName the JNDI name of the {@link Cache} instance that should be used, or null if the cache is to be created
228 * with a cache factory {@link #getCacheFactoryJndiName() found in JNDI} using the specified
229 * {@link #getCacheConfigurationName() cache configuration name}.
230 * @see #getCacheJndiName()
231 * @see #getCacheConfigurationName()
232 * @see #getCacheFactoryJndiName()
233 */
234 public synchronized void setCacheJndiName( String cacheJndiName ) {
235 if (this.cacheJndiName == cacheJndiName || this.cacheJndiName != null && this.cacheJndiName.equals(cacheJndiName)) return; // unchanged
236 this.cacheJndiName = cacheJndiName;
237 }
238
239 /**
240 * Get the name in JNDI of a {@link CacheFactory} instance that should be used to create the cache for this source.
241 * <p>
242 * This source first attempts to find an existing cache in {@link #getCacheJndiName() JNDI}. If none is found, then it
243 * attempts to create a cache instance using the {@link CacheFactory} found in {@link #getCacheFactoryJndiName() JNDI} (or the
244 * {@link DefaultCacheFactory} if no such factory is available) and the {@link #getCacheConfigurationName() cache
245 * configuration name} if supplied or the default configuration if not set.
246 * </p>
247 *
248 * @return the JNDI name of the {@link CacheFactory} instance that should be used, or null if the {@link DefaultCacheFactory}
249 * should be used if a cache is to be created
250 * @see #setCacheFactoryJndiName(String)
251 * @see #getCacheConfigurationName()
252 * @see #getCacheJndiName()
253 */
254 public String getCacheFactoryJndiName() {
255 return cacheFactoryJndiName;
256 }
257
258 /**
259 * Set the name in JNDI of a {@link CacheFactory} instance that should be used to obtain the {@link Cache} instance used by
260 * this source.
261 * <p>
262 * This source first attempts to find an existing cache in {@link #getCacheJndiName() JNDI}. If none is found, then it
263 * attempts to create a cache instance using the {@link CacheFactory} found in {@link #getCacheFactoryJndiName() JNDI} (or the
264 * {@link DefaultCacheFactory} if no such factory is available) and the {@link #getCacheConfigurationName() cache
265 * configuration name} if supplied or the default configuration if not set.
266 * </p>
267 *
268 * @param jndiName the JNDI name of the {@link CacheFactory} instance that should be used, or null if the
269 * {@link DefaultCacheFactory} should be used if a cache is to be created
270 * @see #setCacheFactoryJndiName(String)
271 * @see #getCacheConfigurationName()
272 * @see #getCacheJndiName()
273 */
274 public synchronized void setCacheFactoryJndiName( String jndiName ) {
275 if (this.cacheFactoryJndiName == jndiName || this.cacheFactoryJndiName != null
276 && this.cacheFactoryJndiName.equals(jndiName)) return; // unchanged
277 this.cacheFactoryJndiName = jndiName;
278 }
279
280 /**
281 * Get the name of the configuration that should be used if a {@link Cache cache} is to be created using the
282 * {@link CacheFactory} found in JNDI or the {@link DefaultCacheFactory} if needed.
283 * <p>
284 * This source first attempts to find an existing cache in {@link #getCacheJndiName() JNDI}. If none is found, then it
285 * attempts to create a cache instance using the {@link CacheFactory} found in {@link #getCacheFactoryJndiName() JNDI} (or the
286 * {@link DefaultCacheFactory} if no such factory is available) and the {@link #getCacheConfigurationName() cache
287 * configuration name} if supplied or the default configuration if not set.
288 * </p>
289 *
290 * @return the name of the configuration that should be passed to the {@link CacheFactory}, or null if the default
291 * configuration should be used
292 * @see #setCacheConfigurationName(String)
293 * @see #getCacheFactoryJndiName()
294 * @see #getCacheJndiName()
295 */
296 public String getCacheConfigurationName() {
297 return cacheConfigurationName;
298 }
299
300 /**
301 * Get the name of the configuration that should be used if a {@link Cache cache} is to be created using the
302 * {@link CacheFactory} found in JNDI or the {@link DefaultCacheFactory} if needed.
303 * <p>
304 * This source first attempts to find an existing cache in {@link #getCacheJndiName() JNDI}. If none is found, then it
305 * attempts to create a cache instance using the {@link CacheFactory} found in {@link #getCacheFactoryJndiName() JNDI} (or the
306 * {@link DefaultCacheFactory} if no such factory is available) and the {@link #getCacheConfigurationName() cache
307 * configuration name} if supplied or the default configuration if not set.
308 * </p>
309 *
310 * @param cacheConfigurationName the name of the configuration that should be passed to the {@link CacheFactory}, or null if
311 * the default configuration should be used
312 * @see #getCacheConfigurationName()
313 * @see #getCacheFactoryJndiName()
314 * @see #getCacheJndiName()
315 */
316 public synchronized void setCacheConfigurationName( String cacheConfigurationName ) {
317 if (this.cacheConfigurationName == cacheConfigurationName || this.cacheConfigurationName != null
318 && this.cacheConfigurationName.equals(cacheConfigurationName)) return; // unchanged
319 this.cacheConfigurationName = cacheConfigurationName;
320 }
321
322 /**
323 * Get the UUID of the root node for the cache. If the cache exists, this UUID is not used but is instead set to the UUID of
324 * the existing root node.
325 *
326 * @return the UUID of the root node for the cache.
327 */
328 public String getRootNodeUuid() {
329 return this.rootNodeUuid.toString();
330 }
331
332 /**
333 * Get the UUID of the root node for the cache. If the cache exists, this UUID is not used but is instead set to the UUID of
334 * the existing root node.
335 *
336 * @return the UUID of the root node for the cache.
337 */
338 public UUID getRootNodeUuidObject() {
339 return this.rootNodeUuid;
340 }
341
342 /**
343 * Set the UUID of the root node in this repository. If the cache exists, this UUID is not used but is instead set to the UUID
344 * of the existing root node.
345 *
346 * @param rootNodeUuid the UUID of the root node for the cache, or null if the UUID should be randomly generated
347 */
348 public synchronized void setRootNodeUuid( String rootNodeUuid ) {
349 UUID uuid = null;
350 if (rootNodeUuid == null) uuid = UUID.randomUUID();
351 else uuid = UUID.fromString(rootNodeUuid);
352 if (this.rootNodeUuid.equals(uuid)) return; // unchanged
353 this.rootNodeUuid = uuid;
354 }
355
356 /**
357 * Get the name of the default workspace.
358 *
359 * @return the name of the workspace that should be used by default; never null
360 */
361 public String getNameOfDefaultWorkspace() {
362 return defaultWorkspace;
363 }
364
365 /**
366 * Set the name of the workspace that should be used when clients don't specify a workspace.
367 *
368 * @param nameOfDefaultWorkspace the name of the workspace that should be used by default, or null if the
369 * {@link #DEFAULT_NAME_OF_DEFAULT_WORKSPACE default name} should be used
370 */
371 public synchronized void setNameOfDefaultWorkspace( String nameOfDefaultWorkspace ) {
372 this.defaultWorkspace = nameOfDefaultWorkspace != null ? nameOfDefaultWorkspace : DEFAULT_NAME_OF_DEFAULT_WORKSPACE;
373 }
374
375 /**
376 * Gets the names of the workspaces that are available when this source is created.
377 *
378 * @return the names of the workspaces that this source starts with, or null if there are no such workspaces
379 * @see #setPredefinedWorkspaceNames(String[])
380 * @see #setCreatingWorkspacesAllowed(boolean)
381 */
382 public synchronized String[] getPredefinedWorkspaceNames() {
383 String[] copy = new String[predefinedWorkspaces.length];
384 System.arraycopy(predefinedWorkspaces, 0, copy, 0, predefinedWorkspaces.length);
385 return copy;
386 }
387
388 /**
389 * Sets the names of the workspaces that are available when this source is created.
390 *
391 * @param predefinedWorkspaceNames the names of the workspaces that this source should start with, or null if there are no
392 * such workspaces
393 * @see #setCreatingWorkspacesAllowed(boolean)
394 * @see #getPredefinedWorkspaceNames()
395 */
396 public synchronized void setPredefinedWorkspaceNames( String[] predefinedWorkspaceNames ) {
397 this.predefinedWorkspaces = predefinedWorkspaceNames;
398 }
399
400 /**
401 * Get whether this source allows workspaces to be created dynamically.
402 *
403 * @return true if this source allows workspaces to be created by clients, or false if the
404 * {@link #getPredefinedWorkspaceNames() set of workspaces} is fixed
405 * @see #setPredefinedWorkspaceNames(String[])
406 * @see #getPredefinedWorkspaceNames()
407 * @see #setCreatingWorkspacesAllowed(boolean)
408 */
409 public boolean isCreatingWorkspacesAllowed() {
410 return capabilities.supportsCreatingWorkspaces();
411 }
412
413 /**
414 * Set whether this source allows workspaces to be created dynamically.
415 *
416 * @param allowWorkspaceCreation true if this source allows workspaces to be created by clients, or false if the
417 * {@link #getPredefinedWorkspaceNames() set of workspaces} is fixed
418 * @see #setPredefinedWorkspaceNames(String[])
419 * @see #getPredefinedWorkspaceNames()
420 * @see #isCreatingWorkspacesAllowed()
421 */
422 public synchronized void setCreatingWorkspacesAllowed( boolean allowWorkspaceCreation ) {
423 capabilities = new RepositorySourceCapabilities(true, capabilities.supportsUpdates(), false, allowWorkspaceCreation,
424 capabilities.supportsReferences());
425 }
426
427 /**
428 * {@inheritDoc}
429 *
430 * @see org.jboss.dna.graph.connector.RepositorySource#getConnection()
431 */
432 @SuppressWarnings( "unchecked" )
433 public synchronized RepositoryConnection getConnection() throws RepositorySourceException {
434 if (getName() == null) {
435 I18n msg = JBossCacheConnectorI18n.propertyIsRequired;
436 throw new RepositorySourceException(getName(), msg.text("name"));
437 }
438 if (this.workspaces == null) {
439 Context context = getContext();
440 if (context == null) {
441 try {
442 context = new InitialContext();
443 } catch (NamingException err) {
444 throw new RepositorySourceException(name, err);
445 }
446 }
447
448 // Look for a cache factory in JNDI ...
449 CacheFactory<Name, Object> cacheFactory = null;
450 String jndiName = getCacheFactoryJndiName();
451 if (jndiName != null && jndiName.trim().length() != 0) {
452 Object object = null;
453 try {
454 object = context.lookup(jndiName);
455 if (object != null) cacheFactory = (CacheFactory<Name, Object>)object;
456 } catch (ClassCastException err) {
457 I18n msg = JBossCacheConnectorI18n.objectFoundInJndiWasNotCacheFactory;
458 String className = object != null ? object.getClass().getName() : "null";
459 throw new RepositorySourceException(getName(), msg.text(jndiName, this.getName(), className), err);
460 } catch (Throwable err) {
461 if (err instanceof RuntimeException) throw (RuntimeException)err;
462 throw new RepositorySourceException(getName(), err);
463 }
464 }
465 if (cacheFactory == null) cacheFactory = new DefaultCacheFactory<Name, Object>();
466
467 // Get the default cache configuration name
468 String configName = this.getCacheConfigurationName();
469
470 // Create the set of initial names ...
471 Set<String> initialNames = new HashSet<String>();
472 for (String initialName : getPredefinedWorkspaceNames())
473 initialNames.add(initialName);
474
475 // Now create the workspace manager ...
476 this.workspaces = new JBossCacheWorkspaces(getName(), cacheFactory, configName, initialNames, context);
477 }
478
479 return new JBossCacheConnection(this, this.workspaces);
480 }
481
482 /**
483 * @return repositoryContext
484 */
485 protected RepositoryContext getRepositoryContext() {
486 return repositoryContext;
487 }
488
489 protected Observer getObserver() {
490 return repositoryContext != null ? repositoryContext.getObserver() : null;
491 }
492
493 protected Context getContext() {
494 return this.jndiContext;
495 }
496
497 protected synchronized void setContext( Context context ) {
498 this.jndiContext = context;
499 }
500
501 /**
502 * {@inheritDoc}
503 */
504 @Override
505 public boolean equals( Object obj ) {
506 if (obj == this) return true;
507 if (obj instanceof JBossCacheSource) {
508 JBossCacheSource that = (JBossCacheSource)obj;
509 if (this.getName() == null) {
510 if (that.getName() != null) return false;
511 } else {
512 if (!this.getName().equals(that.getName())) return false;
513 }
514 return true;
515 }
516 return false;
517 }
518
519 /**
520 * {@inheritDoc}
521 */
522 public synchronized Reference getReference() {
523 String className = getClass().getName();
524 String factoryClassName = this.getClass().getName();
525 Reference ref = new Reference(className, factoryClassName, null);
526
527 ref.add(new StringRefAddr(SOURCE_NAME, getName()));
528 ref.add(new StringRefAddr(ROOT_NODE_UUID, getRootNodeUuid().toString()));
529 ref.add(new StringRefAddr(CACHE_JNDI_NAME, getCacheJndiName()));
530 ref.add(new StringRefAddr(CACHE_FACTORY_JNDI_NAME, getCacheFactoryJndiName()));
531 ref.add(new StringRefAddr(CACHE_CONFIGURATION_NAME, getCacheConfigurationName()));
532 ref.add(new StringRefAddr(RETRY_LIMIT, Integer.toString(getRetryLimit())));
533 ref.add(new StringRefAddr(DEFAULT_WORKSPACE, getNameOfDefaultWorkspace()));
534 ref.add(new StringRefAddr(ALLOW_CREATING_WORKSPACES, Boolean.toString(isCreatingWorkspacesAllowed())));
535 String[] workspaceNames = getPredefinedWorkspaceNames();
536 if (workspaceNames != null && workspaceNames.length != 0) {
537 ref.add(new StringRefAddr(PREDEFINED_WORKSPACE_NAMES, StringUtil.combineLines(workspaceNames)));
538 }
539 if (getDefaultCachePolicy() != null) {
540 ByteArrayOutputStream baos = new ByteArrayOutputStream();
541 CachePolicy policy = getDefaultCachePolicy();
542 try {
543 ObjectOutputStream oos = new ObjectOutputStream(baos);
544 oos.writeObject(policy);
545 ref.add(new BinaryRefAddr(DEFAULT_CACHE_POLICY, baos.toByteArray()));
546 } catch (IOException e) {
547 I18n msg = JBossCacheConnectorI18n.errorSerializingCachePolicyInSource;
548 throw new RepositorySourceException(getName(), msg.text(policy.getClass().getName(), getName()), e);
549 }
550 }
551 return ref;
552 }
553
554 /**
555 * {@inheritDoc}
556 */
557 public Object getObjectInstance( Object obj,
558 javax.naming.Name name,
559 Context nameCtx,
560 Hashtable<?, ?> environment ) throws Exception {
561 if (obj instanceof Reference) {
562 Map<String, Object> values = new HashMap<String, Object>();
563 Reference ref = (Reference)obj;
564 Enumeration<?> en = ref.getAll();
565 while (en.hasMoreElements()) {
566 RefAddr subref = (RefAddr)en.nextElement();
567 if (subref instanceof StringRefAddr) {
568 String key = subref.getType();
569 Object value = subref.getContent();
570 if (value != null) values.put(key, value.toString());
571 } else if (subref instanceof BinaryRefAddr) {
572 String key = subref.getType();
573 Object value = subref.getContent();
574 if (value instanceof byte[]) {
575 // Deserialize ...
576 ByteArrayInputStream bais = new ByteArrayInputStream((byte[])value);
577 ObjectInputStream ois = new ObjectInputStream(bais);
578 value = ois.readObject();
579 values.put(key, value);
580 }
581 }
582 }
583 String sourceName = (String)values.get(SOURCE_NAME);
584 String rootNodeUuidString = (String)values.get(ROOT_NODE_UUID);
585 String cacheJndiName = (String)values.get(CACHE_JNDI_NAME);
586 String cacheFactoryJndiName = (String)values.get(CACHE_FACTORY_JNDI_NAME);
587 String cacheConfigurationName = (String)values.get(CACHE_CONFIGURATION_NAME);
588 Object defaultCachePolicy = values.get(DEFAULT_CACHE_POLICY);
589 String retryLimit = (String)values.get(RETRY_LIMIT);
590 String defaultWorkspace = (String)values.get(DEFAULT_WORKSPACE);
591 String createWorkspaces = (String)values.get(ALLOW_CREATING_WORKSPACES);
592
593 String combinedWorkspaceNames = (String)values.get(PREDEFINED_WORKSPACE_NAMES);
594 String[] workspaceNames = null;
595 if (combinedWorkspaceNames != null) {
596 List<String> paths = StringUtil.splitLines(combinedWorkspaceNames);
597 workspaceNames = paths.toArray(new String[paths.size()]);
598 }
599
600 // Create the source instance ...
601 JBossCacheSource source = new JBossCacheSource();
602 if (sourceName != null) source.setName(sourceName);
603 if (rootNodeUuidString != null) source.setRootNodeUuid(rootNodeUuidString);
604 if (cacheJndiName != null) source.setCacheJndiName(cacheJndiName);
605 if (cacheFactoryJndiName != null) source.setCacheFactoryJndiName(cacheFactoryJndiName);
606 if (cacheConfigurationName != null) source.setCacheConfigurationName(cacheConfigurationName);
607 if (defaultCachePolicy instanceof CachePolicy) {
608 source.setDefaultCachePolicy((CachePolicy)defaultCachePolicy);
609 }
610 if (retryLimit != null) source.setRetryLimit(Integer.parseInt(retryLimit));
611 if (defaultWorkspace != null) source.setNameOfDefaultWorkspace(defaultWorkspace);
612 if (createWorkspaces != null) source.setCreatingWorkspacesAllowed(Boolean.parseBoolean(createWorkspaces));
613 if (workspaceNames != null && workspaceNames.length != 0) source.setPredefinedWorkspaceNames(workspaceNames);
614 return source;
615 }
616 return null;
617 }
618 }