aboutsummaryrefslogtreecommitdiffstats
path: root/trunk/infrastructure/yuicompressor/src/com/yahoo/platform/yui/compressor/JarClassLoader.java
blob: a6d3e13f40aa684687e9a3ce52519a04b6aa6d24 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*
 * YUI Compressor
 * Author: Julien Lecomte <jlecomte@yahoo-inc.com>
 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
 * Code licensed under the BSD License:
 *     http://developer.yahoo.net/yui/license.txt
 */

package com.yahoo.platform.yui.compressor;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class JarClassLoader extends ClassLoader {

    private static String jarPath;

    public Class loadClass(String name) throws ClassNotFoundException {

        // First check if the class is already loaded
        Class c = findLoadedClass(name);
        if (c == null) {
            c = findClass(name);
        }

        if (c == null) {
            c = ClassLoader.getSystemClassLoader().loadClass(name);
        }

        return c;
    }

    private static String getJarPath() {

        if (jarPath != null) {
            return jarPath;
        }

        String classname = JarClassLoader.class.getName().replace('.', '/') + ".class";
        String classpath = System.getProperty("java.class.path");
        String classpaths[] = classpath.split(System.getProperty("path.separator"));

        for (int i = 0; i < classpaths.length; i++) {

            String path = classpaths[i];
            JarFile jarFile = null;
            JarEntry jarEntry = null;

            try {
                jarFile = new JarFile(path);
                jarEntry = findJarEntry(jarFile, classname);
            } catch (IOException ioe) {
                /* ignore */
            } finally {
                if (jarFile != null) {
                    try {
                        jarFile.close();
                    } catch (IOException ioe) {
                        /* ignore */
                    }
                }
            }

            if (jarEntry != null) {
                jarPath = path;
                break;
            }
        }

        return jarPath;
    }

    private static JarEntry findJarEntry(JarFile jarFile, String entryName) {

        Enumeration entries = jarFile.entries();

        while (entries.hasMoreElements()) {
            JarEntry entry = (JarEntry) entries.nextElement();
            if (entry.getName().equals(entryName)) {
                return entry;
            }
        }

        return null;
    }

    protected Class findClass(String name) {

        Class c = null;
        String jarPath = getJarPath();

        if (jarPath != null) {
            JarFile jarFile = null;
            try {
                jarFile = new JarFile(jarPath);
                c = loadClassData(jarFile, name);
            } catch (IOException ioe) {
                /* ignore */
            } finally {
                if (jarFile != null) {
                    try {
                        jarFile.close();
                    } catch (IOException ioe) {
                        /* ignore */
                    }
                }
            }
        }

        return c;
    }

    private Class loadClassData(JarFile jarFile, String className) {

        String entryName = className.replace('.', '/') + ".class";
        JarEntry jarEntry = findJarEntry(jarFile, entryName);
        if (jarEntry == null) {
            return null;
        }

        // Create the necessary package if needed...
        int index = className.lastIndexOf('.');
        if (index >= 0) {
            String packageName = className.substring(0, index);
            if (getPackage(packageName) == null) {
                definePackage(packageName, "", "", "", "", "", "", null);
            }
        }

        // Read the Jar File entry and define the class...
        Class c = null;
        try {
            InputStream is = jarFile.getInputStream(jarEntry);
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            copy(is, os);
            byte[] bytes = os.toByteArray();
            c = defineClass(className, bytes, 0, bytes.length);
        } catch (IOException ioe) {
            /* ignore */
        }

        return c;
    }

    private void copy(InputStream in, OutputStream out) throws IOException {
        byte[] buf = new byte[1024];
        while (true) {
            int len = in.read(buf);
            if (len < 0) break;
            out.write(buf, 0, len);
        }
    }
}