View Javadoc

1   /*
2    * Copyright 2011-2013 smartics, Kronseder & Reiner GmbH
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 de.smartics.util.lang;
17  
18  import java.io.IOException;
19  import java.io.InputStream;
20  import java.net.MalformedURLException;
21  import java.net.URL;
22  import java.util.Enumeration;
23  
24  import org.apache.commons.lang.ObjectUtils;
25  
26  /**
27   * A constraint on resources to be loaded from the class path.
28   */
29  public final class ClassPathContext
30  {
31    // ********************************* Fields *********************************
32  
33    // --- constants ------------------------------------------------------------
34  
35    // --- members --------------------------------------------------------------
36  
37    /**
38     * The class loader to load the directory listings.
39     */
40    private final ClassLoader classLoader;
41  
42    /**
43     * Selects the archive root to load from.
44     */
45    private final String archiveRoot;
46  
47    // ****************************** Initializer *******************************
48  
49    // ****************************** Constructors ******************************
50  
51    /**
52     * Default constructor.
53     *
54     * @param classLoader the class loader to load the directory listings.
55     * @param archiveRoot the value for archiveRoot.
56     * @throws NullPointerException if {@code classLoader} is <code>null</code>.
57     */
58    public ClassPathContext(final ClassLoader classLoader,
59        final String archiveRoot) throws NullPointerException
60    {
61      Arg.checkNotNull("classLoader", classLoader);
62  
63      this.classLoader = classLoader;
64      this.archiveRoot = archiveRoot;
65    }
66  
67    // ****************************** Inner Classes *****************************
68  
69    // ********************************* Methods ********************************
70  
71    // --- init -----------------------------------------------------------------
72  
73    // --- get&set --------------------------------------------------------------
74  
75    // --- business -------------------------------------------------------------
76  
77    /**
78     * Constructs the URL to the resource.
79     *
80     * @param resource the resource whose URL is requested.
81     * @return the URL to the resource or <code>null</code> if the resource cannot
82     *         be found on the class path.
83     */
84    public URL getResource(final String resource)
85    {
86      if (archiveRoot == null)
87      {
88        return classLoader.getResource(resource);
89      }
90  
91      // TODO: maybe we should simply construct the URL?
92      try
93      {
94        for (final Enumeration<URL> en = classLoader.getResources(resource); en
95            .hasMoreElements();)
96        {
97          final URL current = en.nextElement();
98          final String urlString = current.toExternalForm();
99          if (urlString.startsWith(archiveRoot))
100         {
101           return current;
102         }
103       }
104     }
105     catch (final IOException e)
106     {
107       // return null
108     }
109     return null;
110   }
111 
112   /**
113    * Opens the stream to the resource.
114    *
115    * @param resource the resource whose stream is requested.
116    * @return the stream to the resource or <code>null</code> if the resource
117    *         cannot be found on the class path. If a stream is returned, the
118    *         client is responsible to close that stream.
119    */
120   public InputStream getResourceAsStream(final String resource)
121   {
122     final URL url = getResource(resource);
123     if (url != null)
124     {
125       try
126       {
127         return url.openStream();
128       }
129       catch (final IOException e)
130       {
131         // return null;
132       }
133     }
134     return null;
135   }
136 
137   /**
138    * Constructs the URL to the resource.
139    *
140    * @param resource the resource whose URL is requested.
141    * @return the constructed URL.
142    * @throws IllegalArgumentException if the URL to the resource cannot be
143    *           constructed.
144    */
145   public URL createUrl(final String resource) throws IllegalArgumentException
146   {
147     try
148     {
149       final String urlString =
150           (archiveRoot != null ? archiveRoot : "") + resource;
151       return new URL(urlString);
152     }
153     catch (final MalformedURLException e)
154     {
155       throw new IllegalArgumentException("Cannot construct URL with resource '"
156                                          + resource + "'.", e);
157     }
158   }
159 
160   // --- object basics --------------------------------------------------------
161 
162   /**
163    * Returns the hash code of the object.
164    *
165    * @return the hash code.
166    */
167   @Override
168   public int hashCode()
169   {
170     return ObjectUtils.hashCode(archiveRoot);
171   }
172 
173   /**
174    * Returns <code>true</code> if the given object is semantically equal to the
175    * given object, <code>false</code> otherwise.
176    *
177    * @param object the instance to compare to.
178    * @return <code>true</code> if the given object is semantically equal to the
179    *         given object, <code>false</code> otherwise.
180    */
181   @Override
182   public boolean equals(final Object object)
183   {
184     if (this == object)
185     {
186       return true;
187     }
188     else if (object == null || getClass() != object.getClass())
189     {
190       return false;
191     }
192 
193     final ClassPathContext other = (ClassPathContext) object;
194 
195     return ObjectUtils.equals(archiveRoot, other.archiveRoot);
196   }
197 
198   @Override
199   public String toString()
200   {
201     return archiveRoot != null ? archiveRoot : "<unspecified archive root>";
202   }
203 }