source: release-kits/lirk3/resources/gs3-release-maker/apache-ant-1.6.5/src/main/org/apache/tools/ant/loader/AntClassLoader2.java@ 14982

Last change on this file since 14982 was 14982, checked in by oranfry, 16 years ago

initial import of LiRK3

File size: 10.9 KB
Line 
1/*
2 * Copyright 2003-2004 The Apache Software Foundation
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 */
17package org.apache.tools.ant.loader;
18
19import java.io.File;
20import java.io.IOException;
21import java.io.InputStream;
22import java.io.InputStreamReader;
23import java.io.Reader;
24import org.apache.tools.ant.AntClassLoader;
25import org.apache.tools.ant.Project;
26import java.util.jar.Manifest;
27import java.util.jar.JarFile;
28import java.util.zip.ZipFile;
29import java.util.jar.Attributes;
30import java.util.jar.Attributes.Name;
31import java.net.URL;
32import java.net.MalformedURLException;
33import java.util.zip.ZipEntry;
34import java.util.Collections;
35import java.util.HashMap;
36import java.util.Map;
37import java.util.StringTokenizer;
38import org.apache.tools.ant.util.FileUtils;
39
40/**
41 * An implementation of the AntClassLoader suitable for use on post JDK 1.1
42 * platforms
43 *
44 */
45public class AntClassLoader2 extends AntClassLoader {
46 /** Instance of a utility class to use for file operations. */
47 private FileUtils fileUtils;
48
49 /** Static map of jar file/time to manifiest class-path entries */
50 private static Map pathMap = Collections.synchronizedMap(new HashMap());
51
52 /**
53 * Constructor
54 */
55 public AntClassLoader2() {
56 fileUtils = FileUtils.newFileUtils();
57 }
58
59 /**
60 * Define a class given its bytes
61 *
62 * @param container the container from which the class data has been read
63 * may be a directory or a jar/zip file.
64 *
65 * @param classData the bytecode data for the class
66 * @param className the name of the class
67 *
68 * @return the Class instance created from the given data
69 *
70 * @throws IOException if the class data cannot be read.
71 */
72 protected Class defineClassFromData(File container, byte[] classData,
73 String className) throws IOException {
74
75 definePackage(container, className);
76 return defineClass(className, classData, 0, classData.length,
77 Project.class.getProtectionDomain());
78
79 }
80
81 /**
82 * Get the manifest from the given jar, if it is indeed a jar and it has a
83 * manifest
84 *
85 * @param container the File from which a manifest is required.
86 *
87 * @return the jar's manifest or null is the container is not a jar or it
88 * has no manifest.
89 *
90 * @exception IOException if the manifest cannot be read.
91 */
92 private Manifest getJarManifest(File container) throws IOException {
93 if (container.isDirectory()) {
94 return null;
95 }
96 JarFile jarFile = null;
97 try {
98 jarFile = new JarFile(container);
99 return jarFile.getManifest();
100 } finally {
101 if (jarFile != null) {
102 jarFile.close();
103 }
104 }
105 }
106
107 /**
108 * Define the package information associated with a class.
109 *
110 * @param container the file containing the class definition.
111 * @param className the class name of for which the package information
112 * is to be determined.
113 *
114 * @exception IOException if the package information cannot be read from the
115 * container.
116 */
117 protected void definePackage(File container, String className)
118 throws IOException {
119 int classIndex = className.lastIndexOf('.');
120 if (classIndex == -1) {
121 return;
122 }
123
124 String packageName = className.substring(0, classIndex);
125 if (getPackage(packageName) != null) {
126 // already defined
127 return;
128 }
129
130 // define the package now
131 Manifest manifest = getJarManifest(container);
132
133 if (manifest == null) {
134 definePackage(packageName, null, null, null, null, null,
135 null, null);
136 } else {
137 definePackage(container, packageName, manifest);
138 }
139 }
140
141 /**
142 * Define the package information when the class comes from a
143 * jar with a manifest
144 *
145 * @param container the jar file containing the manifest
146 * @param packageName the name of the package being defined.
147 * @param manifest the jar's manifest
148 */
149 protected void definePackage(File container, String packageName,
150 Manifest manifest) {
151 String sectionName = packageName.replace('.', '/') + "/";
152
153 String specificationTitle = null;
154 String specificationVendor = null;
155 String specificationVersion = null;
156 String implementationTitle = null;
157 String implementationVendor = null;
158 String implementationVersion = null;
159 String sealedString = null;
160 URL sealBase = null;
161
162 Attributes sectionAttributes = manifest.getAttributes(sectionName);
163 if (sectionAttributes != null) {
164 specificationTitle
165 = sectionAttributes.getValue(Name.SPECIFICATION_TITLE);
166 specificationVendor
167 = sectionAttributes.getValue(Name.SPECIFICATION_VENDOR);
168 specificationVersion
169 = sectionAttributes.getValue(Name.SPECIFICATION_VERSION);
170 implementationTitle
171 = sectionAttributes.getValue(Name.IMPLEMENTATION_TITLE);
172 implementationVendor
173 = sectionAttributes.getValue(Name.IMPLEMENTATION_VENDOR);
174 implementationVersion
175 = sectionAttributes.getValue(Name.IMPLEMENTATION_VERSION);
176 sealedString
177 = sectionAttributes.getValue(Name.SEALED);
178 }
179
180 Attributes mainAttributes = manifest.getMainAttributes();
181 if (mainAttributes != null) {
182 if (specificationTitle == null) {
183 specificationTitle
184 = mainAttributes.getValue(Name.SPECIFICATION_TITLE);
185 }
186 if (specificationVendor == null) {
187 specificationVendor
188 = mainAttributes.getValue(Name.SPECIFICATION_VENDOR);
189 }
190 if (specificationVersion == null) {
191 specificationVersion
192 = mainAttributes.getValue(Name.SPECIFICATION_VERSION);
193 }
194 if (implementationTitle == null) {
195 implementationTitle
196 = mainAttributes.getValue(Name.IMPLEMENTATION_TITLE);
197 }
198 if (implementationVendor == null) {
199 implementationVendor
200 = mainAttributes.getValue(Name.IMPLEMENTATION_VENDOR);
201 }
202 if (implementationVersion == null) {
203 implementationVersion
204 = mainAttributes.getValue(Name.IMPLEMENTATION_VERSION);
205 }
206 if (sealedString == null) {
207 sealedString
208 = mainAttributes.getValue(Name.SEALED);
209 }
210 }
211
212 if (sealedString != null && sealedString.equalsIgnoreCase("true")) {
213 try {
214 sealBase = new URL("file:" + container.getPath());
215 } catch (MalformedURLException e) {
216 // ignore
217 }
218 }
219
220 definePackage(packageName, specificationTitle, specificationVersion,
221 specificationVendor, implementationTitle,
222 implementationVersion, implementationVendor, sealBase);
223 }
224
225
226 /**
227 * Add a file to the path. This classloader reads the manifest, if
228 * available, and adds any additional class path jars specified in the
229 * manifest.
230 *
231 * @param pathComponent the file which is to be added to the path for
232 * this class loader
233 *
234 * @throws IOException if data needed from the file cannot be read.
235 */
236 protected void addPathFile(File pathComponent) throws IOException {
237 super.addPathFile(pathComponent);
238
239 if (pathComponent.isDirectory()) {
240 return;
241 }
242
243 String absPathPlusTimeAndLength =
244 pathComponent.getAbsolutePath() + pathComponent.lastModified() + "-"
245 + pathComponent.length();
246 String classpath = (String) pathMap.get(absPathPlusTimeAndLength);
247 if (classpath == null) {
248 ZipFile jarFile = null;
249 InputStream manifestStream = null;
250 try {
251 jarFile = new ZipFile(pathComponent);
252 manifestStream
253 = jarFile.getInputStream(new ZipEntry("META-INF/MANIFEST.MF"));
254
255 if (manifestStream == null) {
256 return;
257 }
258 Reader manifestReader
259 = new InputStreamReader(manifestStream, "UTF-8");
260 org.apache.tools.ant.taskdefs.Manifest manifest
261 = new org.apache.tools.ant.taskdefs.Manifest(manifestReader);
262 classpath
263 = manifest.getMainSection().getAttributeValue("Class-Path");
264
265 } catch (org.apache.tools.ant.taskdefs.ManifestException e) {
266 // ignore
267 } finally {
268 if (manifestStream != null) {
269 manifestStream.close();
270 }
271 if (jarFile != null) {
272 jarFile.close();
273 }
274 }
275 if (classpath == null) {
276 classpath = "";
277 }
278 pathMap.put(absPathPlusTimeAndLength, classpath);
279 }
280
281 if (!"".equals(classpath)) {
282 URL baseURL = fileUtils.getFileURL(pathComponent);
283 StringTokenizer st = new StringTokenizer(classpath);
284 while (st.hasMoreTokens()) {
285 String classpathElement = st.nextToken();
286 URL libraryURL = new URL(baseURL, classpathElement);
287 if (!libraryURL.getProtocol().equals("file")) {
288 log("Skipping jar library " + classpathElement
289 + " since only relative URLs are supported by this"
290 + " loader", Project.MSG_VERBOSE);
291 continue;
292 }
293 File libraryFile = new File(libraryURL.getFile());
294 if (libraryFile.exists() && !isInPath(libraryFile)) {
295 addPathFile(libraryFile);
296 }
297 }
298 }
299 }
300}
301
Note: See TracBrowser for help on using the repository browser.