001: /*
002: * The contents of this file are subject to the terms
003: * of the Common Development and Distribution License
004: * (the "License"). You may not use this file except
005: * in compliance with the License.
006: *
007: * You can obtain a copy of the license at
008: * https://jwsdp.dev.java.net/CDDLv1.0.html
009: * See the License for the specific language governing
010: * permissions and limitations under the License.
011: *
012: * When distributing Covered Code, include this CDDL
013: * HEADER in each file and include the License file at
014: * https://jwsdp.dev.java.net/CDDLv1.0.html If applicable,
015: * add the following below this CDDL HEADER, with the
016: * fields enclosed by brackets "[]" replaced with your
017: * own identifying information: Portions Copyright [yyyy]
018: * [name of copyright owner]
019: */
020: package com.sun.codemodel;
021:
022: import java.io.IOException;
023: import java.io.OutputStream;
024: import java.io.OutputStreamWriter;
025: import java.io.Writer;
026: import java.nio.charset.CharsetEncoder;
027:
028: import com.sun.codemodel.util.EncoderFactory;
029: import com.sun.codemodel.util.UnicodeEscapeWriter;
030:
031: /**
032: * Receives generated code and writes to the appropriate storage.
033: *
034: * @author
035: * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
036: */
037: public abstract class CodeWriter {
038:
039: /**
040: * Called by CodeModel to store the specified file.
041: * The callee must allocate a storage to store the specified file.
042: *
043: * <p>
044: * The returned stream will be closed before the next file is
045: * stored. So the callee can assume that only one OutputStream
046: * is active at any given time.
047: *
048: * @param pkg
049: * The package of the file to be written.
050: * @param fileName
051: * File name without the path. Something like
052: * "Foo.java" or "Bar.properties"
053: */
054: public abstract OutputStream openBinary(JPackage pkg,
055: String fileName) throws IOException;
056:
057: /**
058: * Called by CodeModel to store the specified file.
059: * The callee must allocate a storage to store the specified file.
060: *
061: * <p>
062: * The returned stream will be closed before the next file is
063: * stored. So the callee can assume that only one OutputStream
064: * is active at any given time.
065: *
066: * @param pkg
067: * The package of the file to be written.
068: * @param fileName
069: * File name without the path. Something like
070: * "Foo.java" or "Bar.properties"
071: */
072: public Writer openSource(JPackage pkg, String fileName)
073: throws IOException {
074: final OutputStreamWriter bw = new OutputStreamWriter(
075: openBinary(pkg, fileName));
076:
077: // create writer
078: try {
079: return new UnicodeEscapeWriter(bw) {
080: // can't change this signature to Encoder because
081: // we can't have Encoder in method signature
082: private final CharsetEncoder encoder = EncoderFactory
083: .createEncoder(bw.getEncoding());
084:
085: protected boolean requireEscaping(int ch) {
086: // control characters
087: if (ch < 0x20 && " \t\r\n".indexOf(ch) == -1)
088: return true;
089: // check ASCII chars, for better performance
090: if (ch < 0x80)
091: return false;
092:
093: return !encoder.canEncode((char) ch);
094: }
095: };
096: } catch (Throwable t) {
097: return new UnicodeEscapeWriter(bw);
098: }
099: }
100:
101: /**
102: * Called by CodeModel at the end of the process.
103: */
104: public abstract void close() throws IOException;
105: }
|