KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > apt > core > internal > JarFactoryContainer


1 /*******************************************************************************
2  * Copyright (c) 2005, 2007 BEA Systems, Inc.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * mkaufman@bea.com - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.jdt.apt.core.internal;
13
14 import java.io.BufferedReader JavaDoc;
15 import java.io.File JavaDoc;
16 import java.io.IOException JavaDoc;
17 import java.io.InputStream JavaDoc;
18 import java.io.InputStreamReader JavaDoc;
19 import java.util.LinkedHashMap JavaDoc;
20 import java.util.Map JavaDoc;
21 import java.util.jar.JarEntry JavaDoc;
22 import java.util.jar.JarFile JavaDoc;
23
24 import org.eclipse.jdt.apt.core.internal.util.FactoryContainer;
25
26 /**
27  * Represents a jar file that contains annotation processor factories.
28  * The factories are listed in the jar's META-INF/services folder, in
29  * a file named com.sun.mirror.apt.AnnotationProcessorFactory.
30  */

31 public abstract class JarFactoryContainer extends FactoryContainer
32 {
33     
34     /**
35      * @return a java.io.File. The file is not guaranteed to exist.
36      */

37     public abstract File JavaDoc getJarFile();
38     
39     @Override JavaDoc
40     public boolean exists() {
41         try {
42             final File JavaDoc jarFile = getJarFile();
43             if(jarFile == null)
44                 return false;
45             return getJarFile().exists();
46         } catch (SecurityException JavaDoc e) {
47             return false;
48         }
49     }
50
51     @Override JavaDoc
52     protected Map JavaDoc<String JavaDoc, String JavaDoc> loadFactoryNames() throws IOException JavaDoc {
53         return getServiceClassnamesFromJar( getJarFile() );
54     }
55     
56     /**
57      * Given a jar file, get the names of any AnnotationProcessorFactory
58      * implementations it offers. The information is based on the Sun
59      * <a HREF="http://java.sun.com/j2se/1.5.0/docs/guide/jar/jar.html#Service%20Provider">
60      * Jar Service Provider spec</a>: the jar file contains a META-INF/services
61      * directory; that directory contains text files named according to the desired
62      * interfaces; and each file contains the names of the classes implementing
63      * the specified service. The files may also contain whitespace (which is to
64      * be ignored). The '#' character indicates the beginning of a line comment,
65      * also to be ignored. Implied but not stated in the spec is that this routine
66      * also ignores anything after the first nonwhitespace token on a line.
67      * @param jar the jar file.
68      * @return a list, possibly empty, of fully qualified classnames to be instantiated.
69      */

70     protected static Map JavaDoc<String JavaDoc, String JavaDoc> getServiceClassnamesFromJar(File JavaDoc jar) throws IOException JavaDoc
71     {
72         Map JavaDoc<String JavaDoc, String JavaDoc> classNames = new LinkedHashMap JavaDoc<String JavaDoc, String JavaDoc>();
73         JarFile JavaDoc jarFile = null;
74         try {
75             jarFile = new JarFile JavaDoc(jar);
76
77             for (String JavaDoc serviceName : AUTOLOAD_SERVICES) {
78                 String JavaDoc providerName = "META-INF/services/" + serviceName; //$NON-NLS-1$
79
// Get the service provider def file out of the jar.
80
JarEntry JavaDoc provider = jarFile.getJarEntry(providerName);
81                 if (provider == null) {
82                     continue;
83                 }
84                 // Extract classnames from the service provider def file.
85
InputStream JavaDoc is = jarFile.getInputStream(provider);
86                 readServiceProvider(is, serviceName, classNames);
87             }
88         }
89         finally {
90             try {if (jarFile != null) jarFile.close();} catch (IOException JavaDoc ioe) {}
91         }
92         return classNames;
93     }
94     
95     /**
96      * Read service classnames from a service provider definition.
97      * @param is an input stream corresponding to a Sun-style service provider
98      * definition file, e.g., one of the files named in AUTOLOAD_SERVICES.
99      * @param classNames a list to which the classes named in is will be added.
100      */

101     protected static void readServiceProvider(InputStream JavaDoc is, String JavaDoc serviceName, Map JavaDoc<String JavaDoc, String JavaDoc> classNames) throws IOException JavaDoc {
102         BufferedReader JavaDoc rd = null;
103         try {
104             rd = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(is, "UTF-8")); //$NON-NLS-1$
105
for (String JavaDoc line = rd.readLine(); line != null; line = rd.readLine()) {
106                 // hack off any comments
107
int iComment = line.indexOf('#');
108                 if (iComment >= 0) {
109                     line = line.substring(0, iComment);
110                 }
111                 // add the first non-whitespace token to the list
112
final String JavaDoc[] tokens = line.split("\\s", 2); //$NON-NLS-1$
113
if (tokens[0].length() > 0) {
114                     classNames.put(tokens[0], serviceName);
115                 }
116             }
117             rd.close();
118         }
119         finally {
120             if (rd != null) try {rd.close();} catch (IOException JavaDoc ioe) {}
121         }
122     }
123     
124     /** List of jar file entries within META-INF/services that specify autoloadable service providers */
125     private static final String JavaDoc[] AUTOLOAD_SERVICES = {
126         AptPlugin.JAVA5_FACTORY_NAME,
127         AptPlugin.JAVA6_FACTORY_NAME
128     };
129     
130 }
131
132
Popular Tags