001// Copyright 2006, 2007, 2008, 2012 The Apache Software Foundation
002//
003// Licensed under the Apache License, Version 2.0 (the "License");
004// you may not use this file except in compliance with the License.
005// You may obtain a copy of the License at
006//
007//     http://www.apache.org/licenses/LICENSE-2.0
008//
009// Unless required by applicable law or agreed to in writing, software
010// distributed under the License is distributed on an "AS IS" BASIS,
011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012// See the License for the specific language governing permissions and
013// limitations under the License.
014
015package org.apache.tapestry5.ioc.internal.util;
016
017import org.apache.tapestry5.ioc.Resource;
018
019import java.net.URL;
020
021/**
022 * Implementation of {@link Resource} for files on the classpath (as defined by a {@link ClassLoader}).
023 */
024public final class ClasspathResource extends AbstractResource
025{
026    private final ClassLoader classLoader;
027
028    // Guarded by lock
029    private URL url;
030
031    // Guarded by lock
032    private boolean urlResolved;
033
034    public ClasspathResource(String path)
035    {
036        this(Thread.currentThread().getContextClassLoader(), path);
037    }
038
039    public ClasspathResource(ClassLoader classLoader, String path)
040    {
041        super(path);
042        assert classLoader != null;
043
044        this.classLoader = classLoader;
045    }
046
047    @Override
048    protected Resource newResource(String path)
049    {
050        return new ClasspathResource(classLoader, path);
051    }
052
053    public URL toURL()
054    {
055        try
056        {
057            acquireReadLock();
058
059            if (!urlResolved)
060            {
061                resolveURL();
062            }
063
064            return url;
065        } finally
066        {
067            releaseReadLock();
068        }
069    }
070
071    private void resolveURL()
072    {
073        try
074        {
075            upgradeReadLockToWriteLock();
076
077            if (!urlResolved)
078            {
079                url = classLoader.getResource(getPath());
080                urlResolved = true;
081            }
082        } finally
083        {
084            downgradeWriteLockToReadLock();
085        }
086    }
087
088    @Override
089    public boolean equals(Object obj)
090    {
091        if (obj == null) return false;
092
093        if (obj == this) return true;
094
095        if (obj.getClass() != getClass()) return false;
096
097        ClasspathResource other = (ClasspathResource) obj;
098
099        return other.classLoader == classLoader && other.getPath().equals(getPath());
100    }
101
102    @Override
103    public int hashCode()
104    {
105        return 227 ^ getPath().hashCode();
106    }
107
108    @Override
109    public String toString()
110    {
111        return "classpath:" + getPath();
112    }
113
114}