| /* |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| |
| package macromedia.abc; |
| |
| import macromedia.asc.util.ByteList; |
| import macromedia.asc.util.ObjectList; |
| |
| import java.io.IOException; |
| import java.io.FileOutputStream; |
| |
| public class Optimizer |
| { |
| public static void main(String[] args) |
| { |
| ObjectList<String> file_names = new ObjectList(); |
| String output_file = "merged.abc"; |
| for( int i = 0; i < args.length; ++i ) |
| { |
| if( args[i].equals("-o") ) |
| { |
| output_file = args[++i]; |
| } |
| else |
| { |
| file_names.add(args[i]); |
| } |
| } |
| |
| BytecodeBuffer[] byte_codes = new BytecodeBuffer[file_names.size()]; |
| for(int i = 0; i < file_names.size(); ++i ) |
| { |
| try |
| { |
| BytecodeBuffer buf = new BytecodeBuffer(file_names.at(i)); |
| byte_codes[i] = buf; |
| } |
| catch( IOException ioe ) |
| { |
| |
| } |
| } |
| byte[] abc = optimize(byte_codes); |
| |
| try |
| { |
| if( abc != null ) |
| { |
| // kkiran close the FileOutputStream, else CP wont be able to |
| // read the merged "abc" file |
| //new FileOutputStream(output_file).write(abc); |
| FileOutputStream fos = new FileOutputStream(output_file); |
| fos.write(abc); |
| fos.close(); |
| } |
| else |
| { |
| System.err.println("Error occurred when merging abc files."); |
| } |
| } |
| catch(IOException ioe ) |
| { |
| ioe.printStackTrace(); |
| } |
| |
| } |
| |
| public static ByteList optimize(ByteList bytes ) |
| { |
| BytecodeBuffer[] byte_codes = new BytecodeBuffer[1]; |
| byte_codes[0] = new BytecodeBuffer(bytes.toByteArray()); |
| byte[] temp = optimize(byte_codes); |
| ByteList new_bytes = new ByteList(temp.length); |
| new_bytes.addAll(temp); |
| return new_bytes; |
| } |
| |
| public static byte[] optimize(BytecodeBuffer[] byte_codes) |
| { |
| int abcSize = byte_codes.length; |
| Decoder[] decoders = new Decoder[abcSize]; |
| ConstantPool[] pools = new ConstantPool[abcSize]; |
| int majorVersion = 0, minorVersion = 0; |
| |
| boolean skipFrame = false; |
| |
| for( int j = 0; j < abcSize; ++j ) |
| { |
| try |
| { |
| // ThreadLocalToolkit.logInfo(tag.name); |
| decoders[j] = new Decoder(byte_codes[j]); |
| if (decoders[j].majorVersion > majorVersion) |
| majorVersion = decoders[j].majorVersion; |
| if (decoders[j].minorVersion > minorVersion) |
| minorVersion = decoders[j].minorVersion; |
| pools[j] = decoders[j].constantPool; |
| } |
| catch (Throwable ex) |
| { |
| ex.printStackTrace(); |
| skipFrame = true; |
| break; |
| } |
| |
| } |
| |
| Encoder encoder = new Encoder(majorVersion, minorVersion); |
| encoder.enablePeepHole(); |
| Decoder decoder = null; |
| // all the constant pools are merged here... |
| try |
| { |
| encoder.addConstantPools(pools); |
| //if (!keepDebugOpcodes) |
| { |
| encoder.disableDebugging(); |
| } |
| // always remove metadata... |
| encoder.removeMetadata(); |
| encoder.configure(decoders); |
| } |
| catch (Throwable ex) |
| { |
| ex.printStackTrace(); |
| return null; |
| } |
| |
| |
| // decode methodInfo... |
| for (int j = 0; j < abcSize; j++) |
| { |
| decoder = decoders[j]; |
| encoder.useConstantPool(j); |
| |
| Decoder.MethodInfo methodInfo = decoder.methodInfo; |
| |
| try |
| { |
| for (int k = 0, infoSize = methodInfo.size(); k < infoSize; k++) |
| { |
| methodInfo.decode(k, encoder); |
| } |
| } |
| catch (Throwable ex) |
| { |
| ex.printStackTrace(); |
| skipFrame = true; |
| break; |
| } |
| } |
| |
| if (skipFrame) |
| { |
| return null; |
| } |
| |
| // decode metadataInfo... |
| for (int j = 0; j < abcSize; j++) |
| { |
| decoder = decoders[j]; |
| encoder.useConstantPool(j); |
| |
| Decoder.MetaDataInfo metadataInfo = decoder.metadataInfo; |
| |
| try |
| { |
| for (int k = 0, infoSize = metadataInfo.size(); k < infoSize; k++) |
| { |
| metadataInfo.decode(k, encoder); |
| } |
| } |
| catch (Throwable ex) |
| { |
| ex.printStackTrace(); |
| skipFrame = true; |
| break; |
| } |
| } |
| |
| if (skipFrame) |
| { |
| return null; |
| } |
| |
| // decode classInfo... |
| |
| for (int j = 0; j < abcSize; j++) |
| { |
| decoder = decoders[j]; |
| encoder.useConstantPool(j); |
| |
| Decoder.ClassInfo classInfo = decoder.classInfo; |
| |
| try |
| { |
| for (int k = 0, infoSize = classInfo.size(); k < infoSize; k++) |
| { |
| classInfo.decodeInstance(k, encoder); |
| } |
| } |
| catch (Throwable ex) |
| { |
| ex.printStackTrace(); |
| skipFrame = true; |
| break; |
| } |
| } |
| |
| if (skipFrame) |
| { |
| return null; |
| } |
| |
| for (int j = 0; j < abcSize; j++) |
| { |
| decoder = decoders[j]; |
| encoder.useConstantPool(j); |
| |
| Decoder.ClassInfo classInfo = decoder.classInfo; |
| |
| try |
| { |
| for (int k = 0, infoSize = classInfo.size(); k < infoSize; k++) |
| { |
| classInfo.decodeClass(k, 0, encoder); |
| } |
| } |
| catch (Throwable ex) |
| { |
| ex.printStackTrace(); |
| skipFrame = true; |
| break; |
| } |
| } |
| |
| if (skipFrame) |
| { |
| return null; |
| } |
| |
| // decode scripts... |
| for (int j = 0; j < abcSize; j++) |
| { |
| decoder = decoders[j]; |
| encoder.useConstantPool(j); |
| |
| Decoder.ScriptInfo scriptInfo = decoder.scriptInfo; |
| |
| try |
| { |
| for (int k = 0, scriptSize = scriptInfo.size(); k < scriptSize; k++) |
| { |
| scriptInfo.decode(k, encoder); |
| } |
| } |
| catch (Throwable ex) |
| { |
| ex.printStackTrace(); |
| skipFrame = true; |
| break; |
| } |
| } |
| |
| if (skipFrame) |
| { |
| return null; |
| } |
| |
| // decode method bodies... |
| for (int j = 0; j < abcSize; j++) |
| { |
| decoder = decoders[j]; |
| encoder.useConstantPool(j); |
| |
| Decoder.MethodBodies methodBodies = decoder.methodBodies; |
| |
| try |
| { |
| for (int k = 0, bodySize = methodBodies.size(); k < bodySize; k++) |
| { |
| methodBodies.decode(k, 2, encoder); |
| } |
| } |
| catch (Throwable ex) |
| { |
| ex.printStackTrace(); |
| skipFrame = true; |
| break; |
| } |
| } |
| |
| if (skipFrame) |
| { |
| return null; |
| } |
| |
| byte[] abc = encoder.toABC(); |
| return abc; |
| } |
| } |