001: /*
002: * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package com.sun.codemodel.internal;
027:
028: import java.io.IOException;
029: import java.io.OutputStream;
030: import java.io.OutputStreamWriter;
031: import java.io.Writer;
032: import java.nio.charset.CharsetEncoder;
033:
034: import com.sun.codemodel.internal.util.EncoderFactory;
035: import com.sun.codemodel.internal.util.UnicodeEscapeWriter;
036:
037: /**
038: * Receives generated code and writes to the appropriate storage.
039: *
040: * @author
041: * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
042: */
043: public abstract class CodeWriter {
044:
045: /**
046: * Called by CodeModel to store the specified file.
047: * The callee must allocate a storage to store the specified file.
048: *
049: * <p>
050: * The returned stream will be closed before the next file is
051: * stored. So the callee can assume that only one OutputStream
052: * is active at any given time.
053: *
054: * @param pkg
055: * The package of the file to be written.
056: * @param fileName
057: * File name without the path. Something like
058: * "Foo.java" or "Bar.properties"
059: */
060: public abstract OutputStream openBinary(JPackage pkg,
061: String fileName) throws IOException;
062:
063: /**
064: * Called by CodeModel to store the specified file.
065: * The callee must allocate a storage to store the specified file.
066: *
067: * <p>
068: * The returned stream will be closed before the next file is
069: * stored. So the callee can assume that only one OutputStream
070: * is active at any given time.
071: *
072: * @param pkg
073: * The package of the file to be written.
074: * @param fileName
075: * File name without the path. Something like
076: * "Foo.java" or "Bar.properties"
077: */
078: public Writer openSource(JPackage pkg, String fileName)
079: throws IOException {
080: final OutputStreamWriter bw = new OutputStreamWriter(
081: openBinary(pkg, fileName));
082:
083: // create writer
084: try {
085: return new UnicodeEscapeWriter(bw) {
086: // can't change this signature to Encoder because
087: // we can't have Encoder in method signature
088: private final CharsetEncoder encoder = EncoderFactory
089: .createEncoder(bw.getEncoding());
090:
091: protected boolean requireEscaping(int ch) {
092: // control characters
093: if (ch < 0x20 && " \t\r\n".indexOf(ch) == -1)
094: return true;
095: // check ASCII chars, for better performance
096: if (ch < 0x80)
097: return false;
098:
099: return !encoder.canEncode((char) ch);
100: }
101: };
102: } catch (Throwable t) {
103: return new UnicodeEscapeWriter(bw);
104: }
105: }
106:
107: /**
108: * Called by CodeModel at the end of the process.
109: */
110: public abstract void close() throws IOException;
111: }
|