All Downloads are FREE. Search and download functionalities are using the official Maven repository.

proguard.io.ClassDataEntryWriter Maven / Gradle / Ivy

Go to download

ProGuardCORE is a free library to read, analyze, modify, and write Java class files.

There is a newer version: 9.1.6
Show newest version
/*
 * ProGuardCORE -- library to process Java bytecode.
 *
 * Copyright (c) 2002-2020 Guardsquare NV
 *
 * Licensed 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 proguard.io;

import java.io.DataOutputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import proguard.classfile.ClassConstants;
import proguard.classfile.ClassPool;
import proguard.classfile.Clazz;
import proguard.classfile.io.ProgramClassWriter;
import proguard.classfile.visitor.ClassVisitor;

/**
 * This {@link DataEntryWriter} finds received class entries in the given class pool and writes them
 * out to the given data entry writer. For resource entries, it returns valid output streams. For
 * class entries, it returns output streams that must not be used.
 *
 * @author Eric Lafortune
 * @see IdleRewriter
 */
public class ClassDataEntryWriter implements DataEntryWriter {
  private final ClassPool classPool;
  private final DataEntryWriter dataEntryWriter;

  private final ClassVisitor extraClassVisitor;

  /**
   * Creates a new ClassDataEntryWriter.
   *
   * @param classPool the class pool in which classes are found.
   * @param dataEntryWriter the writer to which the class file is written.
   */
  public ClassDataEntryWriter(ClassPool classPool, DataEntryWriter dataEntryWriter) {
    this(classPool, dataEntryWriter, null);
  }

  /**
   * Creates a new ClassDataEntryWriter.
   *
   * @param classPool the class pool in which classes are found.
   * @param dataEntryWriter the writer to which the class file is written.
   * @param extraClassVisitor a class visitor that will be visited for each class that is written.
   */
  public ClassDataEntryWriter(
      ClassPool classPool, DataEntryWriter dataEntryWriter, ClassVisitor extraClassVisitor) {
    this.classPool = classPool;
    this.dataEntryWriter = dataEntryWriter;
    this.extraClassVisitor = extraClassVisitor;
  }

  // Implementations for DataEntryWriter.

  @Override
  public boolean createDirectory(DataEntry dataEntry) throws IOException {
    return dataEntryWriter.createDirectory(dataEntry);
  }

  @Override
  public boolean sameOutputStream(DataEntry dataEntry1, DataEntry dataEntry2) throws IOException {
    return dataEntryWriter.sameOutputStream(dataEntry1, dataEntry2);
  }

  @Override
  public OutputStream createOutputStream(DataEntry dataEntry) throws IOException {
    String inputName = dataEntry.getName();

    // Is it a class entry?
    String name = dataEntry.getName();
    if (name.endsWith(ClassConstants.CLASS_FILE_EXTENSION)) {
      // Does it still have a corresponding class?
      String className =
          inputName.substring(0, inputName.length() - ClassConstants.CLASS_FILE_EXTENSION.length());
      Clazz clazz = classPool.getClass(className);
      if (clazz != null) {
        // Rename the data entry if necessary.
        String newClassName = clazz.getName();
        if (!className.equals(newClassName)) {
          dataEntry =
              new RenamedDataEntry(dataEntry, newClassName + ClassConstants.CLASS_FILE_EXTENSION);
        }

        // Get the output stream for this input entry.
        OutputStream outputStream = dataEntryWriter.createOutputStream(dataEntry);
        if (outputStream != null) {
          // Write the class to the output stream.
          DataOutputStream classOutputStream = new DataOutputStream(outputStream);
          try {
            clazz.accept(new ProgramClassWriter(classOutputStream));
            if (extraClassVisitor != null) {
              clazz.accept(extraClassVisitor);
            }
          } catch (RuntimeException e) {
            throw (RuntimeException)
                new RuntimeException(
                        "Unexpected error while writing class ["
                            + className
                            + "] ("
                            + e.getMessage()
                            + ")")
                    .initCause(e);
          } finally {
            classOutputStream.close();
          }
        }
      }

      // Return a dummy, non-null output stream (to work with cascading
      // output writers).
      return new FilterOutputStream(null);
    }

    // Delegate for resource entries.
    return dataEntryWriter.createOutputStream(dataEntry);
  }

  @Override
  public void close() throws IOException {
    // Close the delegate writer.
    dataEntryWriter.close();
  }

  @Override
  public void println(PrintWriter pw, String prefix) {
    pw.println(prefix + "ClassDataEntryWriter");
    dataEntryWriter.println(pw, prefix + "  ");
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy