public AssetSourceImpl(
      ThreadLocale threadLocale,
      Map<String, AssetFactory> configuration,
      SymbolSource symbolSource,
      Logger logger,
      OperationTracker tracker,
      Request request) {
    this.configuration = configuration;
    this.threadLocale = threadLocale;
    this.symbolSource = symbolSource;
    this.logger = logger;
    this.tracker = tracker;
    this.request = request;

    Map<Class, AssetFactory> byResourceClass = CollectionFactory.newMap();

    for (Map.Entry<String, AssetFactory> e : configuration.entrySet()) {
      String prefix = e.getKey();
      AssetFactory factory = e.getValue();

      Resource rootResource = factory.getRootResource();

      byResourceClass.put(rootResource.getClass(), factory);

      prefixToRootResource.put(prefix, rootResource);
    }

    registry = StrategyRegistry.newInstance(AssetFactory.class, byResourceClass);
  }
  @Test
  public void protected_asset_client_URL() {
    ResourceCache cache = mockResourceCache();
    ClasspathAssetAliasManager aliasManager = mockClasspathAssetAliasManager();

    Resource r = new ClasspathResource("foo/Bar.txt");

    train_requiresDigest(cache, r, true);

    expect(cache.getDigest(r)).andReturn("ABC123");

    String expectedClientURL = "/context/asset/foo/Bar.ABC123.txt";

    train_toClientURL(aliasManager, "foo/Bar.ABC123.txt", expectedClientURL);

    EasyMock.expectLastCall().times(2); // 2nd time is the toString() call

    replay();

    AssetFactory factory = new ClasspathAssetFactory(cache, aliasManager);

    Asset asset = factory.createAsset(r);

    assertSame(asset.getResource(), r);
    assertEquals(asset.toClientURL(), expectedClientURL);
    assertEquals(asset.toString(), expectedClientURL);

    verify();
  }
  private Asset createAssetFromResource(Resource resource) {
    // The class of the resource is derived from the class of the base resource.
    // So we can then use the class of the resource as a key to locate the correct asset
    // factory.

    try {
      upgradeReadLockToWriteLock();

      // Check for competing thread beat us to it (not very likely!):

      Asset result = TapestryInternalUtils.getAndDeref(cache, resource);

      if (result != null) {
        return result;
      }

      Class resourceClass = resource.getClass();

      AssetFactory factory = registry.get(resourceClass);

      return factory.createAsset(resource);
    } finally {
      downgradeWriteLockToReadLock();
    }
  }