001: /**
002: * $Id: ResourceLoader.java,v 1.9 2007/01/26 03:47:11 portalbld Exp $
003: * Copyright 2004 Sun Microsystems, Inc. All
004: * rights reserved. Use of this product is subject
005: * to license terms. Federal Acquisitions:
006: * Commercial Software -- Government Users
007: * Subject to Standard License Terms and
008: * Conditions.
009: *
010: * Sun, Sun Microsystems, the Sun logo, and Sun ONE
011: * are trademarks or registered trademarks of Sun Microsystems,
012: * Inc. in the United States and other countries.
013: */package com.sun.portal.util;
014:
015: import java.net.URL;
016: import java.net.MalformedURLException;
017: import java.net.URLClassLoader;
018: import java.security.ProtectionDomain;
019: import java.security.CodeSource;
020: import java.io.File;
021: import java.io.InputStream;
022: import java.io.InputStreamReader;
023: import java.io.FileInputStream;
024: import java.io.IOException;
025: import java.io.FileNotFoundException;
026: import java.util.Properties;
027: import java.util.Map;
028: import java.util.HashMap;
029: import java.util.List;
030: import java.util.ArrayList;
031:
032: /**
033: * A utility class that makes it possible to load the configuration files as
034: * property objects.
035: * There are also some utility methods that allow loading of resources
036: * as streams and also make it possible to get the URL of a resource in either
037: * the portal configuration directory or the software configuration directory
038: */
039: public class ResourceLoader {
040: private static class ResourceLoaderKey {
041: private String pid;
042: private String iid;
043:
044: public ResourceLoaderKey(String pid, String iid) {
045: this .pid = pid;
046: this .iid = iid;
047: }
048:
049: public String getPortalId() {
050: return pid;
051: }
052:
053: public String getInstanceId() {
054: return iid;
055: }
056:
057: public int hashCode() {
058: int hc = 0;
059: if (pid != null) {
060: hc ^= pid.hashCode();
061: }
062: if (iid != null) {
063: hc ^= iid.hashCode();
064: }
065:
066: return hc;
067: }
068:
069: public boolean equals(Object o) {
070: if (!(o instanceof ResourceLoaderKey)) {
071: return false;
072: }
073:
074: ResourceLoaderKey other = (ResourceLoaderKey) o;
075:
076: return fieldEquals(pid, other.pid)
077: && fieldEquals(iid, other.iid);
078: }
079:
080: private static boolean fieldEquals(String s1, String s2) {
081: // equals if:
082: // 1. both are null
083: // 2. both are not null, and are equal
084:
085: if (s1 == null) {
086: if (s2 == null) {
087: return true;
088: }
089: } else if (s1.equals(s2)) {
090: return true;
091: }
092:
093: return false;
094: }
095: }
096:
097: private static Map resourceLoaderMap = new HashMap();
098:
099: public static final String DOMAIN_ID = "com.sun.portal.domain.id";
100: public static final String PORTAL_ID = "com.sun.portal.portal.id";
101: public static final String INSTANCE_ID = "com.sun.portal.instance.id";
102:
103: private ResourceLoaderKey key;
104: private URLClassLoader urlcloader;
105: private Map propsObjectMap = new HashMap();
106:
107: /**
108: * This constructor initializes the classloader with the portal specific
109: * and the instance specific configurations directories in the classpath
110: * to enable the classloader to load the resouces
111: */
112: private ResourceLoader(ResourceLoaderKey key) {
113: this .key = key;
114:
115: try {
116: // Get the PSConfig properties. The PSConfig properties file is
117: // always under the classpath of the classloader that loaded this
118: // ResourceLoader class
119: Properties psConfig = getProperties("PSConfig.properties");
120:
121: String fs = Platform.fs;
122: // Prepare the dirctory names that need to be set as URLs
123: List urls = new ArrayList();
124:
125: String psConfigDir = psConfig.getProperty(
126: "ps.config.location", "")
127: + fs;
128: urls.add(new File(psConfigDir).toURL());
129:
130: String psDataDir = psConfig.getProperty("ps.data.location",
131: "");
132: urls.add(new File(psDataDir).toURL());
133:
134: //
135: // only add the portal id, instance id path components if
136: // the portal id and instance id are specificed
137: //
138:
139: if (getPortalId() != null) {
140: String portalConfigDir = psDataDir + fs + "portals"
141: + fs + getPortalId() + fs + "config" + fs;
142: urls.add(new File(portalConfigDir).toURL());
143:
144: if (getInstanceId() != null) {
145: String instanceConfigDir = portalConfigDir + fs
146: + getInstanceId() + fs;
147: urls.add(new File(instanceConfigDir).toURL());
148: }
149: }
150:
151: // Prepare a set of URLs from the directories
152: URL[] dirs = (URL[]) urls.toArray(new URL[0]);
153:
154: // Get a new instance of the URLClassloader by setting the URLs
155: // and using the previous classloader object
156: urlcloader = URLClassLoader.newInstance(dirs, getCLoader());
157: } catch (MalformedURLException me) {
158: // TODO Log the exception
159: } catch (FileNotFoundException fnfe) {
160: // TODO Log the exception
161: } catch (IOException ioe) {
162: // TODO Log the exception
163: }
164: }
165:
166: private ClassLoader getCLoader() {
167: // The urlcloader reference will be null if
168: // the constructor is trying to fetch the PSConfig.properties.
169: // urlcloader is guaranteed to be non-null after this object's
170: // constructor is complete
171:
172: if (urlcloader == null) {
173: // Return the parent classloader of this ResourceLoader class
174: return this .getClass().getClassLoader();
175: } else {
176: // So the portal ID is available and the constructor created
177: // a url classloader to load portal specific resources.
178: return urlcloader;
179: }
180: }
181:
182: /**
183: * Creates an instance of the ResourceLoader object.
184: * <p>
185: * This method grabs the values for portal, and instance ID
186: * from the given properties object, according to the key names
187: * defined in this class.
188: * <p>
189: * If the Java system properties contain the keys, pass
190: * System.getProperties() to this method.
191: *
192: * @return ResourceLoader object
193: * @param p the properties object containing the
194: * portal and instance IDs.
195: */
196: public static ResourceLoader getInstance(Properties p) {
197: String portalId = p.getProperty(PORTAL_ID);
198: String instanceId = p.getProperty(INSTANCE_ID);
199:
200: return getInstance(portalId, instanceId);
201: }
202:
203: /**
204: * Creates an instance of the ResourceLoader.
205: * <p>
206: * Null values are allowed in the arguments, with some restrictions:
207: * <ul>
208: * <li>if the portal ID is non-null, the domain ID must not be null
209: * <li>if the instance ID is non-null, the portal Id must not be null
210: * </ul>
211: *
212: * @return ResourceLoader object
213: * @param portalId The Domain Identifier as a String
214: * @param portalId The Portal Identifier as a String
215: * @param portalId The Instance Identifier as a String
216: *
217: */
218: public static synchronized ResourceLoader getInstance(
219: String portalId, String instanceId) {
220: // poral ID is required if instance ID is present
221: if (portalId == null && instanceId != null) {
222: throw new RuntimeException("instance ID without portal ID");
223: }
224:
225: ResourceLoaderKey rlk = new ResourceLoaderKey(portalId,
226: instanceId);
227: ResourceLoader rl = (ResourceLoader) resourceLoaderMap.get(rlk);
228: if (rl == null) {
229: rl = new ResourceLoader(rlk);
230: resourceLoaderMap.put(rlk, rl);
231: }
232:
233: return rl;
234: }
235:
236: /**
237: * Creates an instance of the ResourceLoader.
238: * <p>
239: * This method calls getInstance(portalId, null), and will therefore
240: * not consider instance specific paths.
241: *
242: * @return ResourceLoader object
243: * @param portalId The Portal Identifier as a String
244: *
245: */
246: public static synchronized ResourceLoader getInstance(
247: String portalId) {
248: return getInstance(portalId, null);
249: }
250:
251: /**
252: * Creates an instance of the ResourceLoader.
253: * <p>
254: * This method calls getInstance(null, null) and will therefore
255: * only consider software configuration paths.
256: *
257: * @return ResourceLoader object
258: *
259: */
260: public static synchronized ResourceLoader getInstance() {
261: return getInstance(null, null);
262: }
263:
264: /**
265: * Gets and input stream object associated with a resource thats available
266: * to the resource loader
267: *
268: * @param resourceName A string representing the name of the resource.
269: * This string can be an absolute or a relative path.
270: * @throws java.io.FileNotFoundException If the resource is not found in the classpath
271: * @throws java.io.IOException If a stream cannot be opened for this resource
272: * @return An InputStream representing the resource
273: */
274: public InputStream getResourceAsStream(String resourceName)
275: throws FileNotFoundException, IOException {
276:
277: ClassLoader cldr = getCLoader();
278: InputStream in = cldr.getResourceAsStream(resourceName);
279:
280: // If the resource is not found in the classpath of the classloader
281: // then maybe the resource name is an absolute file path
282: if (in == null) {
283: try {
284: // Works if the user has given absolute path
285: in = new FileInputStream(resourceName);
286: } catch (FileNotFoundException e) {
287: // Maybe the file path is relative to this class location
288: try {
289: // Get the location of this class on the filesystem.
290: // Might not work if security is enabled in the Webcontainer
291: ProtectionDomain pd = this .getClass()
292: .getProtectionDomain();
293: if (pd != null) {
294: CodeSource cs = pd.getCodeSource();
295: String loc = cs.getLocation().toString()
296: + resourceName;
297: URL url = new URL(loc);
298: in = url.openStream();
299: }
300: } catch (MalformedURLException mle) {
301: throw e;
302: } catch (IOException ioe) {
303: throw ioe;
304: }
305: }
306: }
307: return in;
308: }
309:
310: /**
311: * This method gets the URL of a given resource that is located
312: * either in the Configuration directory, Portal specific
313: * configuration directory or the instance specific configuration
314: * directory
315: *
316: * @param resourceName The name of the Resource as a String
317: * @return A URL to the resource that is being lookedup. A null is returned
318: * if the resource is not found
319: */
320: public URL getResourceUrl(String resourceName) {
321: ClassLoader cldr = getCLoader();
322: return cldr.getResource(resourceName);
323: }
324:
325: /**
326: * Gets a property object representing a property file in either the portal
327: * configuration directory or the software configuration directory common
328: * to all the portals
329: *
330: * @param propsFileName The name of the property file as a String
331: * @throws FileNotFoundException If a property file does not exist with this
332: * name in the portal configuration or the portal software configuration
333: * directory
334: * @throws java.io.IOException If the property file cannot be loaded as
335: * a property object.
336: * @return a Property object
337: */
338: public synchronized Properties getProperties(String propsFileName)
339: throws FileNotFoundException, IOException {
340: // Try to get it from the cache
341: Properties props = (Properties) propsObjectMap
342: .get(propsFileName);
343:
344: // If null try to load it and put it into cache
345: if (props == null) {
346: InputStream in = getResourceAsStream(propsFileName);
347: if (in != null) {
348: props = new Properties();
349: props.load(in);
350: in.close();
351: propsObjectMap.put(propsFileName, props);
352: }
353: }
354:
355: return props;
356: }
357:
358: /**
359: * Getter for the Portal Identifier value.
360: * May return null.
361: *
362: * @return The portal Id as a String
363: */
364: public String getPortalId() {
365: return key.getPortalId();
366: }
367:
368: /**
369: * Getter for the Portal Server Instance Identifier value.
370: * May return null.
371: *
372: * @return The Portal Server Instance Id as a String
373: */
374: public String getInstanceId() {
375: return key.getInstanceId();
376: }
377: }
|