001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.compress.harmony.pack200; 018 019import org.objectweb.asm.Attribute; 020import org.objectweb.asm.ClassReader; 021import org.objectweb.asm.Label; 022 023/** 024 * NewAttribute extends {@code Attribute} and manages unknown attributes encountered by ASM that have had a layout 025 * definition given to pack200 (e.g. via one of the -C, -M, -F or -D command line options) 026 */ 027public class NewAttribute extends Attribute { 028 029 /** 030 * ErrorAttribute extends {@code NewAttribute} and manages attributes encountered by ASM that have had an error 031 * action specified to pack200 (e.g. via one of the -C, -M, -F or -D command line options such as 032 * -Cattribute-name=error) 033 */ 034 public static class ErrorAttribute extends NewAttribute { 035 036 public ErrorAttribute(final String type, final int context) { 037 super(type, "", context); 038 } 039 040 @Override 041 protected Attribute read(final ClassReader cr, final int off, final int len, final char[] buf, 042 final int codeOff, final Label[] labels) { 043 throw new Error("Attribute " + type + " was found"); 044 } 045 046 } 047 /** 048 * PassAttribute extends {@code NewAttribute} and manages attributes encountered by ASM that have had a pass 049 * action specified to pack200 (e.g. via one of the -C, -M, -F or -D command line options such as 050 * -Cattribute-name=pass) 051 */ 052 public static class PassAttribute extends NewAttribute { 053 054 public PassAttribute(final String type, final int context) { 055 super(type, "", context); 056 } 057 058 @Override 059 protected Attribute read(final ClassReader cr, final int off, final int len, final char[] buf, 060 final int codeOff, final Label[] labels) { 061 throw new Segment.PassException(); 062 } 063 064 } 065 /** 066 * StripAttribute extends {@code NewAttribute} and manages attributes encountered by ASM that have had a strip 067 * action specified to pack200 (e.g. via one of the -C, -M, -F or -D command line options such as 068 * -Cattribute-name=strip) 069 */ 070 public static class StripAttribute extends NewAttribute { 071 072 public StripAttribute(final String type, final int context) { 073 super(type, "", context); 074 } 075 076 @Override 077 protected Attribute read(final ClassReader cr, final int off, final int len, final char[] buf, 078 final int codeOff, final Label[] labels) { 079 // TODO Not sure if this works, can we really strip an attribute if we don't know the layout? 080 return null; 081 } 082 } 083 private boolean contextClass = false; 084 085 private boolean contextMethod = false; 086 private boolean contextField = false; 087 private boolean contextCode = false; 088 private final String layout; 089 private byte[] contents; 090 private int codeOff; 091 092 private Label[] labels; 093 094 private ClassReader classReader; 095 096 private char[] buf; 097 098 public NewAttribute(final ClassReader classReader, final String type, final String layout, final byte[] contents, 099 final char[] buf, final int codeOff, final Label[] labels) { 100 super(type); 101 this.classReader = classReader; 102 this.contents = contents; 103 this.layout = layout; 104 this.codeOff = codeOff; 105 this.labels = labels; 106 this.buf = buf; 107 } 108 109 public NewAttribute(final String type, final String layout, final int context) { 110 super(type); 111 this.layout = layout; 112 addContext(context); 113 } 114 115 public void addContext(final int context) { 116 switch (context) { 117 case AttributeDefinitionBands.CONTEXT_CLASS: 118 contextClass = true; 119 break; 120 case AttributeDefinitionBands.CONTEXT_METHOD: 121 contextMethod = true; 122 break; 123 case AttributeDefinitionBands.CONTEXT_FIELD: 124 contextField = true; 125 break; 126 case AttributeDefinitionBands.CONTEXT_CODE: 127 contextCode = true; 128 break; 129 } 130 } 131 132 public byte[] getBytes() { 133 return contents; 134 } 135 136 public Label getLabel(final int index) { 137 return labels[index]; 138 } 139 140 public String getLayout() { 141 return layout; 142 } 143 144 @Override 145 public boolean isCodeAttribute() { 146 return codeOff != -1; 147 } 148 149 public boolean isContextClass() { 150 return contextClass; 151 } 152 153 public boolean isContextCode() { 154 return contextCode; 155 } 156 157 public boolean isContextField() { 158 return contextField; 159 } 160 161 public boolean isContextMethod() { 162 return contextMethod; 163 } 164 165 @Override 166 public boolean isUnknown() { 167 return false; 168 } 169 170 public boolean isUnknown(final int context) { 171 switch (context) { 172 case AttributeDefinitionBands.CONTEXT_CLASS: 173 return !contextClass; 174 case AttributeDefinitionBands.CONTEXT_METHOD: 175 return !contextMethod; 176 case AttributeDefinitionBands.CONTEXT_FIELD: 177 return !contextField; 178 case AttributeDefinitionBands.CONTEXT_CODE: 179 return !contextCode; 180 } 181 return false; 182 } 183 184 @Override 185 protected Attribute read(final ClassReader cr, final int off, final int len, final char[] buf, final int codeOff, 186 final Label[] labels) { 187 final byte[] attributeContents = new byte[len]; 188 System.arraycopy(cr.b, off, attributeContents, 0, len); 189 return new NewAttribute(cr, type, layout, attributeContents, buf, codeOff, labels); 190 } 191 192 public String readClass(final int index) { 193 return classReader.readClass(index, buf); 194 } 195 196 public Object readConst(final int index) { 197 return classReader.readConst(index, buf); 198 } 199 200 public String readUTF8(final int index) { 201 return classReader.readUTF8(index, buf); 202 } 203}