com.google.gwt.dev.javac.CachedCompilationUnit.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gwt.dev.javac.CachedCompilationUnit.java

Source

/*******************************************************************************
 * Copyright 2011 Google Inc. All Rights Reserved.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * 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 com.google.gwt.dev.javac;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.compiler.CategorizedProblem;

import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.jjs.SourceOrigin;
import com.google.gwt.dev.js.ast.JsFunction;
import com.google.gwt.dev.js.ast.JsProgram;

/**
 * A compilation unit loaded from cache.
 * 
 * XXX Instantiations
 * 
 * @author mitin_aa
 */
public class CachedCompilationUnit extends CompilationUnit {
    private String m_displayLocation;
    private String m_typeName;
    private ContentId m_contentId;
    private long m_lastModified;
    private Collection<CompiledClass> m_compiledClasses;
    private HashSet<ContentId> m_dependencies;
    private boolean m_isSuperSource;
    private ArrayList<JsniMethod> m_jsniMethods;
    private MethodArgNamesLookup m_methodArgs;

    ////////////////////////////////////////////////////////////////////////////
    //
    // Constructor
    //
    ////////////////////////////////////////////////////////////////////////////
    private CachedCompilationUnit() {
        // cannot be instantiated directly
    }

    ////////////////////////////////////////////////////////////////////////////
    //
    // Instantiate
    //
    ////////////////////////////////////////////////////////////////////////////
    public static CachedCompilationUnit load(InputStream inputStream, JsProgram jsProgram) throws Exception {
        DataInputStream dis = new DataInputStream(new BufferedInputStream(inputStream));
        try {
            CachedCompilationUnit compilationUnit = new CachedCompilationUnit();
            // version
            long version = dis.readLong();
            if (version != CompilationUnitDiskCache.CACHE_VERSION) {
                return null;
            }
            // some simple stuff :)
            compilationUnit.m_lastModified = dis.readLong();
            compilationUnit.m_displayLocation = dis.readUTF();
            compilationUnit.m_typeName = dis.readUTF();
            compilationUnit.m_contentId = new ContentId(dis.readUTF());
            compilationUnit.m_isSuperSource = dis.readBoolean();
            // compiled classes
            {
                int size = dis.readInt();
                compilationUnit.m_compiledClasses = new ArrayList<CompiledClass>(size);
                for (int i = 0; i < size; ++i) {
                    // internal name
                    String internalName = dis.readUTF();
                    // is local
                    boolean isLocal = dis.readBoolean();
                    // bytes
                    int byteSize = dis.readInt();
                    byte[] bytes = new byte[byteSize];
                    dis.readFully(bytes);
                    // enclosing class
                    CompiledClass enclosingClass = null;
                    String enclosingClassName = dis.readUTF();
                    if (!StringUtils.isEmpty(enclosingClassName)) {
                        for (CompiledClass cc : compilationUnit.m_compiledClasses) {
                            if (enclosingClassName.equals(cc.getInternalName())) {
                                enclosingClass = cc;
                                break;
                            }
                        }
                    }
                    // some assertion
                    if (!StringUtils.isEmpty(enclosingClassName) && enclosingClass == null) {
                        throw new IllegalStateException("Can't find the enclosing class \"" + enclosingClassName
                                + "\" for \"" + internalName + "\"");
                    }
                    // init unit
                    CompiledClass cc = new CompiledClass(internalName, bytes, isLocal, enclosingClass);
                    cc.initUnit(compilationUnit);
                    compilationUnit.m_compiledClasses.add(cc);
                }
            }
            // dependencies
            {
                compilationUnit.m_dependencies = new HashSet<ContentId>();
                int size = dis.readInt();
                if (size > 0) {
                    for (int i = 0; i < size; i++) {
                        compilationUnit.m_dependencies.add(new ContentId(dis.readUTF()));
                    }
                }
            }
            // JSNI methods
            {
                compilationUnit.m_jsniMethods = new ArrayList<JsniMethod>();
                int size = dis.readInt();
                if (size > 0) {
                    for (int i = 0; i < size; i++) {
                        String name = dis.readUTF();
                        int startPos = dis.readInt();
                        int endPos = dis.readInt();
                        int startLine = dis.readInt();
                        String source = dis.readUTF();
                        String fileName = compilationUnit.m_displayLocation;
                        SourceInfo jsInfo = SourceOrigin.create(startPos, endPos, startLine, fileName);
                        compilationUnit.m_jsniMethods
                                .add(JsniCollector.restoreJsniMethod(name, source, jsInfo, jsProgram));
                    }
                }
            }
            // Method lookup
            {
                compilationUnit.m_methodArgs = MethodArgNamesLookup.load(dis);
            }
            return compilationUnit;
        } finally {
            IOUtils.closeQuietly(dis);
        }
    }

    ////////////////////////////////////////////////////////////////////////////
    //
    // Save
    //
    ////////////////////////////////////////////////////////////////////////////
    public static void save(SourceFileCompilationUnit unit, OutputStream outputStream) throws Exception {
        DataOutputStream dos = null;
        try {
            dos = new DataOutputStream(new BufferedOutputStream(outputStream));
            // version
            dos.writeLong(CompilationUnitDiskCache.CACHE_VERSION);
            // simple stuff
            dos.writeLong(unit.getLastModified());
            dos.writeUTF(unit.getDisplayLocation());
            dos.writeUTF(unit.getTypeName());
            dos.writeUTF(unit.getContentId().get());
            dos.writeBoolean(unit.isSuperSource());
            // compiled classes
            {
                Collection<CompiledClass> compiledClasses = unit.getCompiledClasses();
                int size = compiledClasses.size();
                dos.writeInt(size);
                if (size > 0) {
                    // sort in enclosing order to be able to restore enclosing classes by name
                    CompiledClass[] compiledClassesArray = compiledClasses
                            .toArray(new CompiledClass[compiledClasses.size()]);
                    Arrays.sort(compiledClassesArray, new Comparator<CompiledClass>() {
                        public int compare(CompiledClass o1, CompiledClass o2) {
                            int o1count = countMatches(o1.getInternalName(), Signature.C_DOLLAR);
                            int o2count = countMatches(o2.getInternalName(), Signature.C_DOLLAR);
                            return o1count - o2count;
                        }
                    });
                    // store
                    for (CompiledClass compiledClass : compiledClassesArray) {
                        // internal name
                        dos.writeUTF(compiledClass.getInternalName());
                        // is local
                        dos.writeBoolean(compiledClass.isLocal());
                        // bytes
                        byte[] bytes = compiledClass.getBytes();
                        dos.writeInt(bytes.length);
                        dos.write(bytes);
                        // enclosing class, write the name only
                        CompiledClass enclosingClass = compiledClass.getEnclosingClass();
                        String enclosingClassName = enclosingClass != null ? enclosingClass.getInternalName() : "";
                        dos.writeUTF(enclosingClassName);
                    }
                }
            }
            // dependencies
            {
                Set<ContentId> dependencies = unit.getDependencies();
                int size = dependencies.size();
                dos.writeInt(size);
                if (size > 0) {
                    for (ContentId contentId : dependencies) {
                        dos.writeUTF(contentId.get());
                    }
                }
            }
            // JSNI methods
            {
                List<JsniMethod> jsniMethods = unit.getJsniMethods();
                int size = jsniMethods.size();
                dos.writeInt(size);
                if (size > 0) {
                    for (JsniMethod jsniMethod : jsniMethods) {
                        dos.writeUTF(jsniMethod.name());
                        JsFunction function = jsniMethod.function();
                        SourceInfo sourceInfo = function.getSourceInfo();
                        dos.writeInt(sourceInfo.getStartPos());
                        dos.writeInt(sourceInfo.getEndPos());
                        dos.writeInt(sourceInfo.getStartLine());
                        dos.writeUTF(function.toSource());
                    }
                }
            }
            // Method lookup
            {
                MethodArgNamesLookup methodArgs = unit.getMethodArgs();
                MethodArgNamesLookup.save(methodArgs, dos);
            }
        } finally {
            IOUtils.closeQuietly(dos);
        }
    }

    /**
     * a bit faster then in StringUtils because searches for a char.
     */
    private static int countMatches(String str, char sub) {
        if (StringUtils.isEmpty(str)) {
            return 0;
        }
        int count = 0;
        int idx = 0;
        while ((idx = str.indexOf(sub, idx)) != -1) {
            count++;
            idx += 1;
        }
        return count;
    }

    ////////////////////////////////////////////////////////////////////////////
    //
    // CompilationUnit
    //
    ////////////////////////////////////////////////////////////////////////////
    @Override
    Collection<CompiledClass> getCompiledClasses() {
        return m_compiledClasses;
    }

    @Override
    public long getLastModified() {
        return m_lastModified;
    }

    @Override
    ContentId getContentId() {
        return m_contentId;
    }

    @Override
    public String getTypeName() {
        return m_typeName;
    }

    @Override
    Set<ContentId> getDependencies() {
        return m_dependencies;
    }

    @Override
    public String getDisplayLocation() {
        return m_displayLocation;
    }

    @Override
    public List<JsniMethod> getJsniMethods() {
        return m_jsniMethods;
    }

    @Override
    CategorizedProblem[] getProblems() {
        return null;
    }

    @Override
    public String getSource() {
        return null;
    }

    @Override
    public boolean isGenerated() {
        return false;
    }

    @Override
    public boolean isSuperSource() {
        return m_isSuperSource;
    }

    @Override
    public MethodArgNamesLookup getMethodArgs() {
        return m_methodArgs;
    }
}