1 /*
2 * Copyright 2006-2016 The JGUIraffe Team.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License")
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package net.sf.jguiraffe.locators;
17
18 import java.net.URL;
19
20 import org.apache.commons.lang.ObjectUtils;
21
22 /**
23 * <p>
24 * A specific {@code Locator} implementation that can obtain resources from
25 * the class path.
26 * </p>
27 * <p>
28 * This class is initialized with a resource name. The {@code getURL()}
29 * method tries to find this resource from the class path (using the
30 * {@link LocatorUtils} class. No caching is performed; each invocation of
31 * {@code getURL()} will look up the resource. Because a lookup might depend
32 * on the context class loader, multiple invocations of {@code getURL()} may
33 * yield different results. In addition, it is possible to specify the
34 * class loader to be used for resource lookup.
35 * </p>
36 * <p>
37 * Instances of this class are created using the {@code getInstance()}
38 * factory method. They are immutable and thus can be shared between multiple
39 * threads.
40 * </p>
41 *
42 * @author Oliver Heger
43 * @version $Id: ClassPathLocator.java 211 2012-07-10 19:49:13Z oheger $
44 */
45 public final class ClassPathLocator extends AbstractLocator
46 {
47 /** Stores the name of the resource. */
48 private final String resourceName;
49
50 /** The default class loader for the resource lookup. */
51 private final ClassLoader classLoader;
52
53 /**
54 * Creates a new instance of {@code ClassPathLocator} and sets the name
55 * of the represented resource. To create an instance client code can use
56 * the {@code getInstance()} factory method.
57 *
58 * @param resourceName the resource name
59 * @param cl the default class loader
60 */
61 private ClassPathLocator(String resourceName, ClassLoader cl)
62 {
63 this.resourceName = resourceName;
64 classLoader = cl;
65 }
66
67 /**
68 * Returns the name of the resource represented by this locator.
69 *
70 * @return the resource's name
71 */
72 public String getResourceName()
73 {
74 return resourceName;
75 }
76
77 /**
78 * Returns the default class loader used by this locator when looking up the
79 * resource name. This is the class loader passed to the
80 * {@code getInstance()} method. It may be <b>null</b> if no specific class
81 * loader was provided when constructing this object.
82 *
83 * @return the default class loader for resource lookup
84 * @since 1.2
85 */
86 public ClassLoader getClassLoader()
87 {
88 return classLoader;
89 }
90
91 /**
92 * Returns a {@code ClassPathLocator} instance for the specified
93 * resource name.
94 *
95 * @param resourceName the name of the resource (must not be <b>null</b>)
96 * @return the instance with this resource name
97 * @throws IllegalArgumentException if the resource name is <b>null</b>
98 */
99 public static ClassPathLocator getInstance(String resourceName)
100 {
101 return getInstance(resourceName, null);
102 }
103
104 /**
105 * Returns a {@code ClassPathLocator} instance which looks up the specified
106 * resource name using the given class loader. If a {@code ClassLoader}
107 * reference is provided, this class loader is tried first when resolving
108 * the resource name. Otherwise, the default order of class loaders is used
109 * as implemented in {@link LocatorUtils}.
110 *
111 * @param resourceName the name of the resource (must not be <b>null</b>)
112 * @param cl an optional class loader to be used for resource lookup
113 * @return the instance with this resource name
114 * @throws IllegalArgumentException if the resource name is <b>null</b>
115 * @since 1.2
116 */
117 public static ClassPathLocator getInstance(String resourceName,
118 ClassLoader cl)
119 {
120 if (resourceName == null)
121 {
122 throw new IllegalArgumentException(
123 "Resource name must not be null!");
124 }
125
126 return new ClassPathLocator(resourceName, cl);
127 }
128
129 /**
130 * Returns the URL for the represented resource. This implementation uses
131 * the {@link LocatorUtils#locateResource(String, ClassLoader)} method to
132 * find the resource on the class path. If this fails, an exception is
133 * thrown.
134 *
135 * @return the URL to the resource
136 * @throws LocatorException if the resource URL cannot be obtained
137 */
138 public URL getURL()
139 {
140 URL result = LocatorUtils.locateResource(getResourceName(), getClassLoader());
141 if (result == null)
142 {
143 throw new LocatorException("Cannot locate resource "
144 + getResourceName());
145 }
146
147 return result;
148 }
149
150 /**
151 * Compares this object with another one. Two instances of this class are
152 * equal if and only if they refer to the same resource name and use the
153 * same default class loader.
154 *
155 * @param obj the object to be compared to
156 * @return a flag whether the objects are equal
157 */
158 @Override
159 public boolean equals(Object obj)
160 {
161 if (this == obj)
162 {
163 return true;
164 }
165 if (!(obj instanceof ClassPathLocator))
166 {
167 return false;
168 }
169
170 ClassPathLocator c = (ClassPathLocator) obj;
171 return getResourceName().equals(c.getResourceName())
172 && ObjectUtils.equals(getClassLoader(), c.getClassLoader());
173 }
174
175 /**
176 * Returns a hash code for this object.
177 *
178 * @return a hash code
179 */
180 @Override
181 public int hashCode()
182 {
183 final int factor = 31;
184 int result = getResourceName().hashCode();
185 if (getClassLoader() != null)
186 {
187 result = factor * result + getClassLoader().hashCode();
188 }
189 return result;
190 }
191
192 /**
193 * Returns a string representation of this object. This string will at least
194 * contain the resource name used by this locator.
195 *
196 * @return a string for this object
197 */
198 @Override
199 public String toString()
200 {
201 return LocatorUtils.locatorToString(this, "resourceName = "
202 + getResourceName());
203 }
204 }