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 }