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