blob: bdc698fb2394848a1ed20bcb184fae992f2b6857 [file] [log] [blame]
/*
*
* 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 org.apache.royale.compiler.internal.targets;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import org.apache.royale.compiler.definitions.IDefinition;
import org.apache.royale.compiler.definitions.references.IResolvedQualifiersReference;
import org.apache.royale.compiler.definitions.references.ReferenceFactory;
import org.apache.royale.compiler.internal.definitions.ClassDefinition;
import org.apache.royale.compiler.internal.embedding.transcoders.MovieTranscoder;
import org.apache.royale.compiler.internal.embedding.transcoders.TranscoderBase;
import org.apache.royale.compiler.internal.projects.RoyaleProject;
import org.apache.royale.compiler.internal.units.EmbedCompilationUnit;
import org.apache.royale.compiler.internal.units.ResourceBundleCompilationUnit;
import org.apache.royale.compiler.problems.DependencyNotCompatibleProblem;
import org.apache.royale.compiler.problems.ICompilerProblem;
import org.apache.royale.compiler.units.ICompilationUnit;
import org.apache.royale.compiler.units.ICompilationUnit.UnitType;
import org.apache.royale.compiler.units.requests.IFileScopeRequestResult;
import org.apache.royale.swc.ISWC;
/**
* Abstract base class that contains information about code that uses the flex
* framework that is needed by the compiler to generate code in the first frame
* of royale application SWFs or library.swfs in royale SWCs.
* <p>
* This information is collected by looking at all the {@link ICompilationUnit}s
* that will be built into a royale application SWF or royale SWC.
*/
abstract class RoyaleFrame1Info
{
protected RoyaleFrame1Info(RoyaleProject royaleProject)
{
this.royaleProject = royaleProject;
IResolvedQualifiersReference resourceBundleRef = ReferenceFactory.packageQualifiedReference(
royaleProject.getWorkspace(), royaleProject.getResourceBundleClass());
resourceBundleDefinition = (ClassDefinition)resourceBundleRef.resolve(royaleProject);
// sorted set of resouce bundles
compiledResourceBundleNames = new TreeSet<String>();
embeddedFonts = new TreeMap<String, RoyaleFontInfo>();
problems = new ArrayList<ICompilerProblem>();
}
protected final RoyaleProject royaleProject;
private final ClassDefinition resourceBundleDefinition;
final TreeSet<String> compiledResourceBundleNames;
final TreeMap<String, RoyaleFontInfo> embeddedFonts;
final ArrayList<ICompilerProblem> problems;
/**
* Method called by sub-classes to iterate over all the
* {@link ICompilationUnit}s.
*
* @param builtCompilationUnits {@link Iterable} that can be used to iterate
* over all the {@link ICompilationUnit}s being built into a flex
* application SWF or royale SWC.
* @throws InterruptedException
*/
protected final void collectFromCompilationUnits(Iterable<ICompilationUnit> builtCompilationUnits) throws InterruptedException
{
for(ICompilationUnit cu : builtCompilationUnits)
{
collectFromCompilationUnit(cu);
}
}
/**
* virtual method that sub-classes override to collection information need
* to generate code for frame1 from a particular {@link ICompilationUnit}.
* <p>
* This class collects:
* <ul>
* <li>Resource bundle names</li>
* <li>Embedded font information</li>
* <li>SWC version problems</li>
* </ul>
*
* @param cu The {@link ICompilationUnit} to collect information from.
* @throws InterruptedException
*/
protected void collectFromCompilationUnit(ICompilationUnit cu) throws InterruptedException
{
if (resourceBundleDefinition != null)
collectCompiledResourceBundleNames(cu);
collectEmbeddedFonts(cu);
checkSWCVersioningFilter(problems, cu);
}
/**
* Collects embedded font information from the specified
* {@link ICompilationUnit}.
*
* @param compilationUnit {@link ICompilationUnit} to collect embedded font
* information from.
*/
private final void collectEmbeddedFonts(ICompilationUnit compilationUnit)
{
if (!(compilationUnit instanceof EmbedCompilationUnit))
return;
TranscoderBase transcoder = (TranscoderBase)((EmbedCompilationUnit)compilationUnit).getEmbedData().getTranscoder();
if (!(transcoder instanceof MovieTranscoder))
return;
MovieTranscoder movieTranscoder = (MovieTranscoder)transcoder;
RoyaleFontInfo royaleFontInfo = movieTranscoder.getRoyaleFontInfo();
if (royaleFontInfo != null)
embeddedFonts.put(movieTranscoder.getSymbol(), royaleFontInfo);
}
/**
* Collects the compiled resource bundle names. A resource bundle can exist
* in two different formats. Either it can be a properties file or a class
* that extends mx.resources.ResourceBundle class. This method collects
* names for resource bundles that match either of these two formats.
*
* @throws InterruptedException
*/
private void collectCompiledResourceBundleNames(ICompilationUnit compilationUnit)
throws InterruptedException
{
//this check is lighter than resolving whether it extends ResourceBundle,
//therefore do this for properties files.
if (compilationUnit instanceof ResourceBundleCompilationUnit)
{
//it is a properties file, so add the bundle name to the list
compiledResourceBundleNames.add(((ResourceBundleCompilationUnit)compilationUnit).getBundleNameInColonSyntax());
}
else
{
IFileScopeRequestResult result = compilationUnit.getFileScopeRequest().get();
for(IDefinition def : result.getExternallyVisibleDefinitions())
{
if(def instanceof ClassDefinition)
{
ClassDefinition classDef = (ClassDefinition)def;
//check whether class extends ResourceBundle, but not ResourceBundle.
if(!resourceBundleDefinition.equals(classDef) &&
classDef.isInstanceOf(resourceBundleDefinition, royaleProject))
{
//this is a class that extents mx.resources.ResourceBundle, so add it to the list
compiledResourceBundleNames.add(def.getQualifiedName());
}
}
}
}
}
/**
* Make sure we are not using any SWCs that have a higher minimum version that the
* compatibility version.
*
* @param cu
* @throws InterruptedException
*/
private void checkSWCVersioningFilter(ArrayList<ICompilerProblem> problems, ICompilationUnit cu) throws InterruptedException
{
Integer compatibilityVersion = royaleProject.getCompatibilityVersion();
// if compatibility-version is not set then we won't be doing any filtering.
if (compatibilityVersion == null)
return;
// Only check the dependencies of hand written units
if (cu.getCompilationUnitType() == UnitType.SWC_UNIT)
return;
Set<ICompilationUnit> dependencies = royaleProject.getDependencies(cu);
for (ICompilationUnit dependency : dependencies)
{
if (dependency.getCompilationUnitType() != UnitType.SWC_UNIT)
continue;
ISWC swc = royaleProject.getWorkspace().getSWCManager().get(
new File(dependency.getAbsoluteFilename()));
int royaleMinSupportedVersion = swc.getVersion().getRoyaleMinSupportedVersionInt();
if (compatibilityVersion.intValue() < royaleMinSupportedVersion)
{
problems.add(new DependencyNotCompatibleProblem(dependency.getQualifiedNames().get(0),
dependency.getAbsoluteFilename(),
swc.getVersion().getRoyaleMinSupportedVersion(),
royaleProject.getCompatibilityVersionString()));
}
}
}
/**
* @return A {@link Set} of {@link String}s containing the dotted fully
* qualified names of mix-in classes.
*/
Set<String> getMixins()
{
return Collections.emptySet();
}
}