001 /*
002 * Copyright 2010-2013 JetBrains s.r.o.
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
017 package org.jetbrains.jet.codegen;
018
019 import org.jetbrains.annotations.NotNull;
020 import org.jetbrains.org.objectweb.asm.ClassWriter;
021 import org.jetbrains.org.objectweb.asm.util.TraceClassVisitor;
022
023 import java.io.PrintWriter;
024 import java.io.StringWriter;
025
026 @SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
027 public class ClassBuilderFactories {
028 @NotNull
029 public static ClassBuilderFactory THROW_EXCEPTION = new ClassBuilderFactory() {
030 @NotNull
031 @Override
032 public ClassBuilderMode getClassBuilderMode() {
033 return ClassBuilderMode.FULL;
034 }
035
036 @Override
037 public ClassBuilder newClassBuilder() {
038 throw new IllegalStateException();
039 }
040
041 @Override
042 public String asText(ClassBuilder builder) {
043 throw new IllegalStateException();
044 }
045
046 @Override
047 public byte[] asBytes(ClassBuilder builder) {
048 throw new IllegalStateException();
049 }
050 };
051
052 @NotNull
053 public static ClassBuilderFactory TEST = new ClassBuilderFactory() {
054 @NotNull
055 @Override
056 public ClassBuilderMode getClassBuilderMode() {
057 return ClassBuilderMode.FULL;
058 }
059
060 @Override
061 public ClassBuilder newClassBuilder() {
062 return new TraceBuilder(new BinaryClassWriter());
063 }
064
065 @Override
066 public String asText(ClassBuilder builder) {
067 TraceClassVisitor visitor = (TraceClassVisitor) builder.getVisitor();
068
069 StringWriter writer = new StringWriter();
070 visitor.p.print(new PrintWriter(writer));
071
072 return writer.toString();
073 }
074
075 @Override
076 public byte[] asBytes(ClassBuilder builder) {
077 return ((TraceBuilder) builder).binary.toByteArray();
078 }
079 };
080
081 @NotNull
082 public static ClassBuilderFactory BINARIES = new ClassBuilderFactory() {
083 @NotNull
084 @Override
085 public ClassBuilderMode getClassBuilderMode() {
086 return ClassBuilderMode.FULL;
087 }
088
089 @Override
090 public ClassBuilder newClassBuilder() {
091 return new AbstractClassBuilder.Concrete(new BinaryClassWriter());
092 }
093
094 @Override
095 public String asText(ClassBuilder builder) {
096 throw new UnsupportedOperationException("BINARIES generator asked for text");
097 }
098
099 @Override
100 public byte[] asBytes(ClassBuilder builder) {
101 ClassWriter visitor = (ClassWriter) builder.getVisitor();
102 return visitor.toByteArray();
103 }
104 };
105
106 private ClassBuilderFactories() {
107 }
108
109 private static class BinaryClassWriter extends ClassWriter {
110 public BinaryClassWriter() {
111 super(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
112 }
113
114 @Override
115 protected String getCommonSuperClass(String type1, String type2) {
116 try {
117 return super.getCommonSuperClass(type1, type2);
118 }
119 catch (Throwable t) {
120 // @todo we might need at some point do more sophisticated handling
121 return "java/lang/Object";
122 }
123 }
124 }
125
126 private static class TraceBuilder extends AbstractClassBuilder.Concrete {
127 public final BinaryClassWriter binary;
128
129 public TraceBuilder(BinaryClassWriter binary) {
130 super(new TraceClassVisitor(binary, new PrintWriter(new StringWriter())));
131 this.binary = binary;
132 }
133 }
134 }