001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.java;
031:
032: import com.caucho.bytecode.JClass;
033: import com.caucho.vfs.Path;
034: import com.caucho.vfs.WriteStream;
035:
036: import java.io.IOException;
037: import java.io.Writer;
038:
039: /**
040: * Writing class for generated Java code.
041: */
042: public class JavaWriter extends Writer {
043: // Write stream for generating the code
044: private WriteStream _os;
045:
046: // Indentation depth
047: private int _indentDepth;
048:
049: // True at the start of a line
050: private boolean _startLine = true;
051:
052: // The line mapping
053: private LineMap _lineMap;
054:
055: // The current output line
056: private int _destLine = 1;
057: private boolean _lastCr;
058:
059: // Generates a unique string.
060: private int _uniqueId;
061:
062: public JavaWriter(WriteStream os) {
063: _os = os;
064: }
065:
066: /**
067: * Returns the underlying stream.
068: */
069: public WriteStream getWriteStream() {
070: return _os;
071: }
072:
073: /**
074: * Returns the destination line.
075: */
076: public int getDestLine() {
077: return _destLine;
078: }
079:
080: /**
081: * Sets the line map
082: */
083: public void setLineMap(LineMap lineMap) {
084: _lineMap = lineMap;
085: }
086:
087: /**
088: * Gets the line map
089: */
090: public LineMap getLineMap() {
091: return _lineMap;
092: }
093:
094: /**
095: * Sets the source filename and line.
096: *
097: * @param filename the filename of the source file.
098: * @param line the line of the source file.
099: */
100: public void setLocation(String filename, int line)
101: throws IOException {
102: if (_lineMap != null && filename != null && line >= 0) {
103: _lineMap.add(filename, line, _destLine);
104: }
105: }
106:
107: /**
108: * Generates a unique id.
109: */
110: public int generateId() {
111: return _uniqueId++;
112: }
113:
114: /**
115: * Prints a Java escaped string
116: */
117: public void printJavaString(String s) throws IOException {
118: for (int i = 0; i < s.length(); i++) {
119: char ch = s.charAt(i);
120:
121: switch (ch) {
122: case '\\':
123: _os.print("\\\\");
124: break;
125: case '\n':
126: _os.print("\\n");
127: break;
128: case '\r':
129: _os.print("\\r");
130: break;
131: case '"':
132: _os.print("\\\"");
133: break;
134: default:
135: _os.print(ch);
136: }
137: }
138: }
139:
140: /**
141: * Prints a Java escaped string
142: */
143: public void printJavaChar(char ch) throws IOException {
144: switch (ch) {
145: case '\\':
146: _os.print("\\\\");
147: break;
148: case '\n':
149: _os.print("\\n");
150: break;
151: case '\r':
152: _os.print("\\r");
153: break;
154: case '\'':
155: _os.print("\\'");
156: break;
157: default:
158: _os.print(ch);
159: }
160: }
161:
162: /**
163: * Prints a Java escaped string
164: */
165: public static String escapeJavaString(String s) {
166: StringBuilder sb = new StringBuilder();
167:
168: for (int i = 0; i < s.length(); i++) {
169: char ch = s.charAt(i);
170:
171: switch (ch) {
172: case '\\':
173: sb.append("\\\\");
174: break;
175: case '\n':
176: sb.append("\\n");
177: break;
178: case '\r':
179: sb.append("\\r");
180: break;
181: case '"':
182: sb.append("\\\"");
183: break;
184: default:
185: sb.append(ch);
186: }
187: }
188:
189: return sb.toString();
190: }
191:
192: /**
193: * Pushes an indentation depth.
194: */
195: public void pushDepth() throws IOException {
196: _indentDepth += 2;
197: }
198:
199: /**
200: * Pops an indentation depth.
201: */
202: public void popDepth() throws IOException {
203: _indentDepth -= 2;
204: }
205:
206: /**
207: * Prints a string
208: */
209: public void print(String s) throws IOException {
210: if (_startLine)
211: printIndent();
212:
213: if (s == null) {
214: _lastCr = false;
215: _os.print("null");
216:
217: return;
218: }
219:
220: int len = s.length();
221: for (int i = 0; i < len; i++) {
222: int ch = s.charAt(i);
223:
224: if (ch == '\n' && !_lastCr)
225: _destLine++;
226: else if (ch == '\r')
227: _destLine++;
228:
229: _lastCr = ch == '\r';
230:
231: _os.print((char) ch);
232: }
233: }
234:
235: public void write(char[] buffer, int offset, int length)
236: throws IOException {
237: print(new String(buffer, offset, length));
238: }
239:
240: /**
241: * Prints a character.
242: */
243: public void print(char ch) throws IOException {
244: if (_startLine)
245: printIndent();
246:
247: if (ch == '\r') {
248: _destLine++;
249: } else if (ch == '\n' && !_lastCr)
250: _destLine++;
251:
252: _lastCr = ch == '\r';
253:
254: _os.print(ch);
255: }
256:
257: /**
258: * Prints a boolean.
259: */
260: public void print(boolean b) throws IOException {
261: if (_startLine)
262: printIndent();
263:
264: _os.print(b);
265: _lastCr = false;
266: }
267:
268: /**
269: * Prints an integer.
270: */
271: public void print(int i) throws IOException {
272: if (_startLine)
273: printIndent();
274:
275: _os.print(i);
276: _lastCr = false;
277: }
278:
279: /**
280: * Prints an long
281: */
282: public void print(long l) throws IOException {
283: if (_startLine)
284: printIndent();
285:
286: _os.print(l);
287: _lastCr = false;
288: }
289:
290: /**
291: * Prints an object.
292: */
293: public void print(Object o) throws IOException {
294: if (_startLine)
295: printIndent();
296:
297: _os.print(o);
298: _lastCr = false;
299: }
300:
301: /**
302: * Prints a string with a new line
303: */
304: public void println(String s) throws IOException {
305: print(s);
306: println();
307: }
308:
309: /**
310: * Prints a boolean with a new line
311: */
312: public void println(boolean v) throws IOException {
313: print(v);
314: println();
315: }
316:
317: /**
318: * Prints a character.
319: */
320: public void println(char ch) throws IOException {
321: print(ch);
322: println();
323: }
324:
325: /**
326: * Prints an integer with a new line
327: */
328: public void println(int v) throws IOException {
329: print(v);
330: println();
331: }
332:
333: /**
334: * Prints an long with a new line
335: */
336: public void println(long v) throws IOException {
337: print(v);
338: println();
339: }
340:
341: /**
342: * Prints an object with a new line
343: */
344: public void println(Object v) throws IOException {
345: print(v);
346: println();
347: }
348:
349: /**
350: * Prints a newline
351: */
352: public void println() throws IOException {
353: _os.println();
354: if (!_lastCr)
355: _destLine++;
356: _lastCr = false;
357: _startLine = true;
358: }
359:
360: /**
361: * Prints the Java represention of the class
362: */
363: public void printClass(Class cl) throws IOException {
364: if (!cl.isArray())
365: print(cl.getName().replace('$', '.'));
366: else {
367: printClass(cl.getComponentType());
368: print("[]");
369: }
370: }
371:
372: /**
373: * Converts a java primitive type to a Java object.
374: *
375: * @param value the java expression to be converted
376: * @param javaType the type of the converted expression.
377: */
378: public void printJavaTypeToObject(String value, Class javaType)
379: throws IOException {
380: if (Object.class.isAssignableFrom(javaType))
381: print(value);
382: else if (javaType.equals(boolean.class))
383: print("new Boolean(" + value + ")");
384: else if (javaType.equals(byte.class))
385: print("new Byte(" + value + ")");
386: else if (javaType.equals(short.class))
387: print("new Short(" + value + ")");
388: else if (javaType.equals(int.class))
389: print("new Integer(" + value + ")");
390: else if (javaType.equals(long.class))
391: print("new Long(" + value + ")");
392: else if (javaType.equals(char.class))
393: print("String.valueOf(" + value + ")");
394: else if (javaType.equals(float.class))
395: print("new Float(" + value + ")");
396: else if (javaType.equals(double.class))
397: print("new Double(" + value + ")");
398: else
399: print(value);
400: }
401:
402: /**
403: * Converts a java primitive type to a Java object.
404: *
405: * @param value the java expression to be converted
406: * @param javaType the type of the converted expression.
407: */
408: public void printJavaTypeToObject(String value, JClass javaType)
409: throws IOException {
410: if (javaType.getName().equals("boolean"))
411: print("new Boolean(" + value + ")");
412: else if (javaType.getName().equals("byte"))
413: print("new Byte(" + value + ")");
414: else if (javaType.getName().equals("short"))
415: print("new Short(" + value + ")");
416: else if (javaType.getName().equals("int"))
417: print("new Integer(" + value + ")");
418: else if (javaType.getName().equals("long"))
419: print("new Long(" + value + ")");
420: else if (javaType.getName().equals("char"))
421: print("String.valueOf(" + value + ")");
422: else if (javaType.getName().equals("float"))
423: print("new Float(" + value + ")");
424: else if (javaType.getName().equals("double"))
425: print("new Double(" + value + ")");
426: else
427: print(value);
428: }
429:
430: /**
431: * Prints the indentation at the beginning of a line.
432: */
433: public void printIndent() throws IOException {
434: _startLine = false;
435:
436: for (int i = 0; i < _indentDepth; i++)
437: _os.print(' ');
438:
439: _lastCr = false;
440: }
441:
442: /**
443: * Generates the smap file.
444: */
445: public void generateSmap() throws IOException {
446: if (_lineMap != null) {
447: Path dstPath = getWriteStream().getPath();
448: Path smap = dstPath.getParent().lookup(
449: dstPath.getTail() + ".smap");
450:
451: WriteStream out = smap.openWrite();
452: try {
453: String srcName = _lineMap.getLastSourceFilename();
454:
455: LineMapWriter writer = new LineMapWriter(out);
456:
457: if (_lineMap.getSourceType() != null)
458: writer.setSourceType(_lineMap.getSourceType());
459:
460: writer.write(_lineMap);
461: } finally {
462: out.close();
463: }
464: }
465: }
466:
467: /**
468: * Returns the error message with proper line number.
469: */
470: public String errorMessage(String message) {
471: /*
472: if (_srcFilename == null)
473: return message;
474: else
475: return _srcFilename + ':' + _srcLine + ": " + message;
476: */
477: return message;
478: }
479:
480: public void flush() {
481: }
482:
483: public void close() {
484: }
485: }
|