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 }