1 /**
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one or more
4 * contributor license agreements. See the NOTICE file distributed with
5 * this work for additional information regarding copyright ownership.
6 * The ASF licenses this file to You under the Apache License, Version 2.0
7 * (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 package org.apache.geronimo.system.rmi;
20
21 import java.net.MalformedURLException;
22 import java.net.URL;
23
24 import java.io.File;
25
26 import java.util.StringTokenizer;
27
28 import java.rmi.server.RMIClassLoader;
29 import java.rmi.server.RMIClassLoaderSpi;
30
31 import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
32
33 /**
34 * An implementation of {@link RMIClassLoaderSpi} which provides normilzation
35 * of codebase URLs and delegates to the default {@link RMIClassLoaderSpi}.
36 *
37 * @version $Rev: 470597 $ $Date: 2006-11-02 15:30:55 -0800 (Thu, 02 Nov 2006) $
38 */
39 public class RMIClassLoaderSpiImpl
40 extends RMIClassLoaderSpi
41 {
42 private RMIClassLoaderSpi delegate = RMIClassLoader.getDefaultProviderInstance();
43
44
45 private ConcurrentHashMap cachedCodebases = new ConcurrentHashMap(100, 0.75F);
46
47
48 public Class loadClass(String codebase, String name, ClassLoader defaultLoader)
49 throws MalformedURLException, ClassNotFoundException
50 {
51 if (codebase != null) {
52 codebase = getNormalizedCodebase(codebase);
53 }
54
55 return delegate.loadClass(codebase, name, defaultLoader);
56 }
57
58 public Class loadProxyClass(String codebase, String[] interfaces, ClassLoader defaultLoader)
59 throws MalformedURLException, ClassNotFoundException
60 {
61 if (codebase != null) {
62 codebase = getNormalizedCodebase(codebase);
63 }
64
65 return delegate.loadProxyClass(codebase, interfaces, defaultLoader);
66 }
67
68 public ClassLoader getClassLoader(String codebase)
69 throws MalformedURLException
70 {
71 if (codebase != null) {
72 codebase = getNormalizedCodebase(codebase);
73 }
74
75 return delegate.getClassLoader(codebase);
76 }
77
78 public String getClassAnnotation(Class type) {
79 Object obj = type.getClassLoader();
80 if (obj instanceof ClassLoaderServerAware) {
81 ClassLoaderServerAware classLoader = (ClassLoaderServerAware) obj;
82 URL urls[] = classLoader.getClassLoaderServerURLs();
83 if (null == urls) {
84 return delegate.getClassAnnotation(type);
85 }
86 StringBuffer codebase = new StringBuffer();
87 for (int i = 0; i < urls.length; i++) {
88 URL url = normalizeURL(urls[i]);
89 if (codebase.length() != 0) {
90 codebase.append(' ');
91 }
92 codebase.append(url);
93 }
94 return codebase.toString();
95 }
96
97 return delegate.getClassAnnotation(type);
98 }
99
100 /**
101 * Uses a ConcurrentReaderHashmap to save the contents of previous parses.
102 *
103 * @param codebase
104 * @return
105 * @throws MalformedURLException
106 */
107 private String getNormalizedCodebase(String codebase)
108 throws MalformedURLException {
109 String cachedCodebase = (String)cachedCodebases.get(codebase);
110 if (cachedCodebase != null)
111 return cachedCodebase;
112
113 String normalizedCodebase = normalizeCodebase(codebase);
114 String oldValue = (String)cachedCodebases.put(codebase, normalizedCodebase);
115
116
117
118 if (oldValue != null) {
119 cachedCodebases.remove(codebase);
120 }
121 return normalizedCodebase;
122 }
123
124
125 static String normalizeCodebase(String input)
126 throws MalformedURLException
127 {
128 assert input != null;
129
130 StringBuffer codebase = new StringBuffer();
131 StringBuffer working = new StringBuffer();
132 StringTokenizer stok = new StringTokenizer(input, " \t\n\r\f", true);
133
134 while (stok.hasMoreTokens()) {
135 String item = stok.nextToken();
136
137
138
139
140
141
142 if ( item.indexOf(':') != -1 )
143 {
144 try {
145 URL url = new URL(item);
146
147
148 updateCodebase(working, codebase);
149 } catch (MalformedURLException ignore) {
150
151 }
152 }
153
154
155 working.append(item);
156 }
157
158
159 updateCodebase(working, codebase);
160
161
162 return codebase.toString();
163 }
164
165 private static void updateCodebase(final StringBuffer working, final StringBuffer codebase)
166 throws MalformedURLException
167 {
168 if (working.length() != 0) {
169
170 URL url = normalizeURL(new URL(working.toString()));
171
172
173
174 if (codebase.length() != 0) {
175 codebase.append(" ");
176 }
177 codebase.append(url);
178
179
180 working.setLength(0);
181 }
182 }
183
184 static URL normalizeURL(URL url)
185 {
186 assert url != null;
187
188 if (url.getProtocol().equals("file")) {
189 String filename = url.getFile().replace('/', File.separatorChar);
190 File file = new File(filename);
191 try {
192 url = file.toURI().toURL();
193 }
194 catch (MalformedURLException ignore) {}
195 }
196
197 return url;
198 }
199
200 public interface ClassLoaderServerAware {
201 public URL[] getClassLoaderServerURLs();
202 }
203 }