001/*
002 *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003 *
004 *  This file is licensed to You under the Eclipse Public License (EPL);
005 *  You may not use this file except in compliance with the License. You
006 *  may obtain a copy of the License at
007 *
008 *      http://www.opensource.org/licenses/eclipse-1.0.php
009 *
010 *  See the COPYRIGHT.txt file distributed with this work for information
011 *  regarding copyright ownership.
012 */
013package org.jikesrvm.util;
014
015import java.io.PrintStream;
016import java.io.PrintWriter;
017
018import org.jikesrvm.VM;
019import org.jikesrvm.classloader.Atom;
020import org.jikesrvm.classloader.RVMMember;
021
022/**
023 * The subclasses of PrintContainer all implement the {@link PrintLN}
024 * interface.  They are used by our {@link java.lang.Throwable} to print stack
025 * traces; it lets one use a single class to operate on {@link PrintWriter}
026 * and {@link PrintStream} output streams and for the {@link VM#sysWrite}
027 * output method.
028 *
029 * <p> We use it so we can print stack traces without having to provide
030 * multiple versions of each method, one for each kind of output stream.
031 */
032public final class PrintContainer {
033  /** Can not be instantiated. */
034  private PrintContainer() {}
035
036  /** Print via PrintWriter */
037  private static class WithPrintWriter extends PrintLN {
038    private final PrintWriter out;
039
040    WithPrintWriter(PrintWriter out) {
041      this.out = out;
042    }
043
044    @Override
045    public void flush() {
046      out.flush();
047    }
048
049    @Override
050    public void println() {
051      out.println();
052    }
053
054    @Override
055    public void print(String s) {
056      if (s == null) {
057        s = "(*null String pointer*)";
058      }
059      out.print(s);
060    }
061
062    @Override
063    public void print(char c) {
064      out.print(c);
065    }
066  }
067
068  /** Print via PrintStream */
069  private static class WithPrintStream extends PrintLN {
070    private final PrintStream out;
071
072    WithPrintStream(PrintStream out) {
073      this.out = out;
074    }
075
076    @Override
077    public boolean isSystemErr() {
078      return this.out == System.err;
079    }
080
081    @Override
082    public void flush() {
083      out.flush();
084    }
085
086    @Override
087    public void println() {
088      out.println();
089    }
090
091    @Override
092    public void print(String s) {
093      if (s == null) {
094        s = "(*null String pointer*)";
095      }
096      out.print(s);
097    }
098
099    @Override
100    public void print(char c) {
101      out.print(c);
102    }
103  }
104
105  public static PrintLN get(PrintStream out) {
106    return new WithPrintStream(out);
107  }
108
109  public static PrintLN get(PrintWriter out) {
110    return new WithPrintWriter(out);
111  }
112
113  // Keep this one ready to go at all times :)
114  public static final PrintLN readyPrinter = new WithSysWrite();
115
116  /** This (nested) class does printing via {@link VM#sysWrite} */
117  private static class WithSysWrite extends PrintLN {
118    /** This doesn't carry any state, but we have a constructor so that we can
119     * pass an instance of this to something expecting a {@link PrintLN} . */
120    WithSysWrite() {}
121
122    @Override
123    public boolean isSysWrite() {
124      return true;
125    }
126
127    @Override
128    public void flush() {
129    }
130
131    @Override
132    public void println() {
133      VM.sysWriteln();
134    }
135
136    @Override
137    public void print(String s) {
138      if (s == null) {
139        s = "(*null String pointer*)";
140      }
141
142      VM.sysWrite(s);
143    }
144
145    @Override
146    public void println(String s) {
147      print(s);
148      println();
149    }
150
151    @Override
152    public void print(int i) {
153      VM.sysWrite(i);
154    }
155
156    @Override
157    public void printHex(int i) {
158      VM.sysWriteHex(i);
159    }
160
161    @Override
162    public void print(char c) {
163      VM.sysWrite(c);
164    }
165
166    @Override
167    public void print(RVMMember m) {
168      VM.sysWrite(m);
169    }
170
171    @Override
172    public void print(Atom a) {
173      VM.sysWrite(a);
174    }
175  }
176}
177