| /* |
| * |
| * 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 flex2.linker; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.LinkedList; |
| import java.util.List; |
| import java.util.Map; |
| |
| import flex2.compiler.CompilationUnit; |
| import flex2.compiler.Source; |
| import flex2.compiler.util.Name; |
| import flex2.compiler.util.QName; |
| import flex2.compiler.util.ThreadLocalToolkit; |
| import flex2.compiler.util.graph.Algorithms; |
| import flex2.compiler.util.graph.DependencyGraph; |
| import flex2.compiler.util.graph.Vertex; |
| import flex2.compiler.util.graph.Visitor; |
| |
| /** |
| * The equivalent of FlexMovie when building a projector, ie a .exe. |
| */ |
| public class ConsoleApplication |
| { |
| public ConsoleApplication(LinkerConfiguration linkerConfiguration) |
| { |
| abcList = new ArrayList<byte[]>(); |
| enableDebugger = linkerConfiguration.debug(); |
| exportedUnits = new LinkedList<CompilationUnit>(); |
| } |
| |
| private List<byte[]> abcList; |
| private byte[] main; |
| public final boolean enableDebugger; |
| private List<CompilationUnit> exportedUnits; |
| |
| public List<byte[]> getABCs() |
| { |
| return abcList; |
| } |
| |
| public void generate(List<CompilationUnit> units) throws LinkerException |
| { |
| // create a dependency graph based on source file dependencies... |
| final DependencyGraph<CompilationUnit> dependencies = extractCompilationUnitInfo(units); |
| exportDependencies(dependencies); |
| |
| if (ThreadLocalToolkit.errorCount() > 0) |
| { |
| throw new LinkerException.LinkingFailed(); |
| } |
| } |
| |
| private DependencyGraph<CompilationUnit> extractCompilationUnitInfo(List<CompilationUnit> units) |
| { |
| final DependencyGraph<CompilationUnit> dependencies = new DependencyGraph<CompilationUnit>(); |
| final Map<QName, String> qnames = new HashMap<QName, String>(); // QName, VirtualFile.getName() |
| |
| for (int i = 0, length = units.size(); i < length; i++) |
| { |
| CompilationUnit u = units.get(i); |
| Source s = u.getSource(); |
| String path = s.getName(); |
| |
| dependencies.put(path, u); |
| if (!dependencies.containsVertex(s.getName())) |
| { |
| dependencies.addVertex(new Vertex<String,CompilationUnit>(path)); |
| } |
| |
| // register QName --> VirtualFile.getName() |
| for (Iterator<QName> j = u.topLevelDefinitions.iterator(); j.hasNext();) |
| { |
| qnames.put(j.next(), s.getName()); |
| } |
| } |
| |
| // setup inheritance-based dependencies... |
| for (int i = 0, size = units.size(); i < size; i++) |
| { |
| CompilationUnit u = units.get(i); |
| Source s = u.getSource(); |
| String head = s.getName(); |
| |
| for (Name name : u.inheritance) |
| { |
| if (name instanceof QName) |
| { |
| QName qname = (QName) name; |
| String tail = qnames.get(qname); |
| |
| if (tail != null && !head.equals(tail) && !dependencies.dependencyExists(head, tail)) |
| { |
| dependencies.addDependency(head, tail); |
| } |
| } |
| } |
| } |
| |
| return dependencies; |
| } |
| |
| private void exportDependencies(final DependencyGraph<CompilationUnit> dependencies) |
| { |
| // export compilation units |
| Algorithms.topologicalSort(dependencies, new Visitor<Vertex<String,CompilationUnit>>() |
| { |
| public void visit(Vertex<String,CompilationUnit> v) |
| { |
| String fileName = v.getWeight(); |
| CompilationUnit u = dependencies.get(fileName); |
| if (!u.getSource().isInternal()) |
| { |
| if (u.isRoot()) |
| { |
| main = u.getByteCodes(); |
| } |
| else |
| { |
| abcList.add(u.getByteCodes()); |
| } |
| exportedUnits.add(u); |
| } |
| } |
| }); |
| |
| abcList.add(main); |
| } |
| |
| public List<CompilationUnit> getExportedUnits() |
| { |
| return exportedUnits; |
| } |
| } |