001: /*
002: * Copyright 1999-2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package com.opensymphony.webwork.util.classloader.compilers.eclipse;
017:
018: import com.opensymphony.webwork.util.classloader.compilers.JavaCompiler;
019: import com.opensymphony.webwork.util.classloader.problems.CompilationProblemHandler;
020: import com.opensymphony.webwork.util.classloader.readers.ResourceReader;
021: import com.opensymphony.webwork.util.classloader.stores.ResourceStore;
022: import org.apache.commons.lang.StringUtils;
023: import org.apache.commons.logging.Log;
024: import org.apache.commons.logging.LogFactory;
025: import org.eclipse.jdt.core.compiler.IProblem;
026: import org.eclipse.jdt.internal.compiler.*;
027: import org.eclipse.jdt.internal.compiler.Compiler;
028: import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
029: import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
030: import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
031: import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
032: import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
033: import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
034:
035: import java.io.ByteArrayOutputStream;
036: import java.io.IOException;
037: import java.io.InputStream;
038: import java.net.URL;
039: import java.util.*;
040:
041: public final class EclipseJavaCompiler implements JavaCompiler {
042:
043: private final static Log log = LogFactory
044: .getLog(EclipseJavaCompiler.class);
045: private final EclipseJavaCompilerSettings settings;
046:
047: public EclipseJavaCompiler() {
048: this (new EclipseJavaCompilerSettings());
049: }
050:
051: public EclipseJavaCompiler(
052: final EclipseJavaCompilerSettings pSettings) {
053: settings = pSettings;
054: }
055:
056: final class CompilationUnit implements ICompilationUnit {
057:
058: final private String clazzName;
059: final private String fileName;
060: final private char[] typeName;
061: final private char[][] packageName;
062: final private ResourceReader reader;
063:
064: CompilationUnit(final ResourceReader pReader,
065: final String pClazzName) {
066: reader = pReader;
067: clazzName = pClazzName;
068: fileName = StringUtils.replaceChars(clazzName, '.', '/')
069: + ".java";
070: int dot = clazzName.lastIndexOf('.');
071: if (dot > 0) {
072: typeName = clazzName.substring(dot + 1).toCharArray();
073: } else {
074: typeName = clazzName.toCharArray();
075: }
076: final StringTokenizer izer = new StringTokenizer(clazzName,
077: ".");
078: packageName = new char[izer.countTokens() - 1][];
079: for (int i = 0; i < packageName.length; i++) {
080: packageName[i] = izer.nextToken().toCharArray();
081: }
082: }
083:
084: public char[] getFileName() {
085: return fileName.toCharArray();
086: }
087:
088: public char[] getContents() {
089: return reader.getContent(fileName);
090: }
091:
092: public char[] getMainTypeName() {
093: return typeName;
094: }
095:
096: public char[][] getPackageName() {
097: return packageName;
098: }
099: }
100:
101: public void compile(final String[] pClazzNames,
102: final ResourceReader pReader, final ResourceStore pStore,
103: final CompilationProblemHandler pProblemHandler) {
104:
105: final Map settingsMap = settings.getMap();
106: final Set clazzIndex = new HashSet();
107: ICompilationUnit[] compilationUnits = new ICompilationUnit[pClazzNames.length];
108: for (int i = 0; i < compilationUnits.length; i++) {
109: final String clazzName = pClazzNames[i];
110: compilationUnits[i] = new CompilationUnit(pReader,
111: clazzName);
112: clazzIndex.add(clazzName);
113: log.debug("compiling " + clazzName);
114: }
115:
116: final IErrorHandlingPolicy policy = DefaultErrorHandlingPolicies
117: .proceedWithAllProblems();
118: final IProblemFactory problemFactory = new DefaultProblemFactory(
119: Locale.getDefault());
120: final INameEnvironment nameEnvironment = new INameEnvironment() {
121:
122: public NameEnvironmentAnswer findType(
123: final char[][] compoundTypeName) {
124: final StringBuffer result = new StringBuffer();
125: for (int i = 0; i < compoundTypeName.length; i++) {
126: if (i != 0) {
127: result.append('.');
128: }
129: result.append(compoundTypeName[i]);
130: }
131: return findType(result.toString());
132: }
133:
134: public NameEnvironmentAnswer findType(
135: final char[] typeName, final char[][] packageName) {
136: final StringBuffer result = new StringBuffer();
137: for (int i = 0; i < packageName.length; i++) {
138: result.append(packageName[i]);
139: result.append('.');
140: }
141: result.append(typeName);
142: return findType(result.toString());
143: }
144:
145: private NameEnvironmentAnswer findType(
146: final String clazzName) {
147: byte[] clazzBytes = pStore.read(clazzName);
148: if (clazzBytes != null) {
149: // log.debug("loading from store " + clazzName);
150: final char[] fileName = clazzName.toCharArray();
151: try {
152: final ClassFileReader classFileReader = new ClassFileReader(
153: clazzBytes, fileName, true);
154: return new NameEnvironmentAnswer(
155: classFileReader, null);
156: } catch (final ClassFormatException e) {
157: log.error("wrong class format", e);
158: }
159: } else {
160: if (pReader.isAvailable(clazzName.replace('.', '/')
161: + ".java")) {
162: log.debug("compile " + clazzName);
163: ICompilationUnit compilationUnit = new CompilationUnit(
164: pReader, clazzName);
165: return new NameEnvironmentAnswer(
166: compilationUnit, null);
167: }
168:
169: final String resourceName = clazzName.replace('.',
170: '/')
171: + ".class";
172: final InputStream is = this .getClass()
173: .getClassLoader().getResourceAsStream(
174: resourceName);
175: if (is != null) {
176: final byte[] buffer = new byte[8192];
177: final ByteArrayOutputStream baos = new ByteArrayOutputStream(
178: buffer.length);
179: int count;
180: try {
181: while ((count = is.read(buffer, 0,
182: buffer.length)) > 0) {
183: baos.write(buffer, 0, count);
184: }
185: baos.flush();
186: clazzBytes = baos.toByteArray();
187: final char[] fileName = clazzName
188: .toCharArray();
189: ClassFileReader classFileReader = new ClassFileReader(
190: clazzBytes, fileName, true);
191: return new NameEnvironmentAnswer(
192: classFileReader, null);
193: } catch (final IOException e) {
194: log.error("could not read class", e);
195: } catch (final ClassFormatException e) {
196: log.error("wrong class format", e);
197: } finally {
198: try {
199: baos.close();
200: } catch (final IOException oe) {
201: log
202: .error(
203: "could not close output stream",
204: oe);
205: }
206: try {
207: is.close();
208: } catch (final IOException ie) {
209: log.error(
210: "could not close input stream",
211: ie);
212: }
213: }
214: }
215: }
216: return null;
217: }
218:
219: private boolean isPackage(final String clazzName) {
220: final String resourceName = clazzName.replace('.', '/')
221: + ".class";
222: final URL resource = this .getClass().getClassLoader()
223: .getResource(resourceName);
224: return resource == null;
225: }
226:
227: public boolean isPackage(char[][] parentPackageName,
228: char[] packageName) {
229: final StringBuffer result = new StringBuffer();
230: if (parentPackageName != null) {
231: for (int i = 0; i < parentPackageName.length; i++) {
232: if (i != 0) {
233: result.append('.');
234: }
235: result.append(parentPackageName[i]);
236: }
237: }
238: if (Character.isUpperCase(packageName[0])) {
239: return false;
240: }
241: if (parentPackageName != null
242: && parentPackageName.length > 0) {
243: result.append('.');
244: }
245: result.append(packageName);
246: return isPackage(result.toString());
247: }
248:
249: public void cleanup() {
250: }
251: };
252:
253: final ICompilerRequestor compilerRequestor = new ICompilerRequestor() {
254: public void acceptResult(CompilationResult result) {
255: if (result.hasProblems()) {
256: if (pProblemHandler != null) {
257: final IProblem[] problems = result
258: .getProblems();
259: for (int i = 0; i < problems.length; i++) {
260: final IProblem problem = problems[i];
261: pProblemHandler
262: .handle(new EclipseCompilationProblem(
263: problem));
264: }
265: }
266: }
267: if (!result.hasErrors()) {
268: final ClassFile[] clazzFiles = result
269: .getClassFiles();
270: for (int i = 0; i < clazzFiles.length; i++) {
271: final ClassFile clazzFile = clazzFiles[i];
272: final char[][] compoundName = clazzFile
273: .getCompoundName();
274: final StringBuffer clazzName = new StringBuffer();
275: for (int j = 0; j < compoundName.length; j++) {
276: if (j != 0) {
277: clazzName.append('.');
278: }
279: clazzName.append(compoundName[j]);
280: }
281: pStore.write(clazzName.toString(), clazzFile
282: .getBytes());
283: }
284: }
285: }
286: };
287:
288: pProblemHandler.onStart();
289:
290: try {
291:
292: final Compiler compiler = new Compiler(nameEnvironment,
293: policy, settingsMap, compilerRequestor,
294: problemFactory);
295:
296: compiler.compile(compilationUnits);
297:
298: } finally {
299: pProblemHandler.onStop();
300: }
301: }
302: }
|