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 definition given to pack200 (e.g. via one of 025 * 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 action specified to pack200 (e.g. via one of 031 * the -C, -M, -F or -D command line options such as -Cattribute-name=error) 032 */ 033 public static class ErrorAttribute extends NewAttribute { 034 035 public ErrorAttribute(final String type, final int context) { 036 super(type, "", context); 037 } 038 039 @Override 040 protected Attribute read(final ClassReader cr, final int off, final int len, final char[] buf, final int codeOff, final Label[] labels) { 041 throw new Error("Attribute " + type + " was found"); 042 } 043 044 } 045 046 /** 047 * PassAttribute extends {@code NewAttribute} and manages attributes encountered by ASM that have had a pass action specified to pack200 (e.g. via one of 048 * the -C, -M, -F or -D command line options such as -Cattribute-name=pass) 049 */ 050 public static class PassAttribute extends NewAttribute { 051 052 public PassAttribute(final String type, final int context) { 053 super(type, "", context); 054 } 055 056 @Override 057 protected Attribute read(final ClassReader cr, final int off, final int len, final char[] buf, final int codeOff, final Label[] labels) { 058 throw new Segment.PassException(); 059 } 060 061 } 062 063 /** 064 * StripAttribute extends {@code NewAttribute} and manages attributes encountered by ASM that have had a strip action specified to pack200 (e.g. via one of 065 * the -C, -M, -F or -D command line options such as -Cattribute-name=strip) 066 */ 067 public static class StripAttribute extends NewAttribute { 068 069 public StripAttribute(final String type, final int context) { 070 super(type, "", context); 071 } 072 073 @Override 074 protected Attribute read(final ClassReader cr, final int off, final int len, final char[] buf, final int codeOff, final Label[] labels) { 075 // TODO Not sure if this works, can we really strip an attribute if we don't know the layout? 076 return null; 077 } 078 } 079 080 private boolean contextClass; 081 082 private boolean contextMethod; 083 private boolean contextField; 084 private boolean contextCode; 085 private final String layout; 086 private byte[] contents; 087 private int codeOff; 088 089 private Label[] labels; 090 091 private ClassReader classReader; 092 093 private char[] buf; 094 095 public NewAttribute(final ClassReader classReader, final String type, final String layout, final byte[] contents, final char[] buf, final int codeOff, 096 final Label[] labels) { 097 super(type); 098 this.classReader = classReader; 099 this.contents = contents; 100 this.layout = layout; 101 this.codeOff = codeOff; 102 this.labels = labels; 103 this.buf = buf; 104 } 105 106 public NewAttribute(final String type, final String layout, final int context) { 107 super(type); 108 this.layout = layout; 109 addContext(context); 110 } 111 112 public void addContext(final int context) { 113 switch (context) { 114 case AttributeDefinitionBands.CONTEXT_CLASS: 115 contextClass = true; 116 break; 117 case AttributeDefinitionBands.CONTEXT_METHOD: 118 contextMethod = true; 119 break; 120 case AttributeDefinitionBands.CONTEXT_FIELD: 121 contextField = true; 122 break; 123 case AttributeDefinitionBands.CONTEXT_CODE: 124 contextCode = true; 125 break; 126 } 127 } 128 129 public byte[] getBytes() { 130 return contents; 131 } 132 133 public Label getLabel(final int index) { 134 return labels[index]; 135 } 136 137 public String getLayout() { 138 return layout; 139 } 140 141 @Override 142 public boolean isCodeAttribute() { 143 return codeOff != -1; 144 } 145 146 public boolean isContextClass() { 147 return contextClass; 148 } 149 150 public boolean isContextCode() { 151 return contextCode; 152 } 153 154 public boolean isContextField() { 155 return contextField; 156 } 157 158 public boolean isContextMethod() { 159 return contextMethod; 160 } 161 162 @Override 163 public boolean isUnknown() { 164 return false; 165 } 166 167 public boolean isUnknown(final int context) { 168 switch (context) { 169 case AttributeDefinitionBands.CONTEXT_CLASS: 170 return !contextClass; 171 case AttributeDefinitionBands.CONTEXT_METHOD: 172 return !contextMethod; 173 case AttributeDefinitionBands.CONTEXT_FIELD: 174 return !contextField; 175 case AttributeDefinitionBands.CONTEXT_CODE: 176 return !contextCode; 177 } 178 return false; 179 } 180 181 @Override 182 protected Attribute read(final ClassReader cr, final int off, final int len, final char[] buf, final int codeOff, final Label[] labels) { 183 final byte[] attributeContents = new byte[len]; 184 System.arraycopy(cr.b, off, attributeContents, 0, len); 185 return new NewAttribute(cr, type, layout, attributeContents, buf, codeOff, labels); 186 } 187 188 public String readClass(final int index) { 189 return classReader.readClass(index, buf); 190 } 191 192 public Object readConst(final int index) { 193 return classReader.readConst(index, buf); 194 } 195 196 public String readUTF8(final int index) { 197 return classReader.readUTF8(index, buf); 198 } 199}