blob: 7325ff74322b58a24d67d2629b7085f2307a7041 [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.caches;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.zip.ZipFile;
import org.apache.royale.compiler.caches.ISWFCache;
import org.apache.royale.compiler.problems.FileInLibraryNotFoundProblem;
import org.apache.royale.swc.ISWC;
import org.apache.royale.swc.SWC;
import org.apache.royale.swc.SWCManager;
import org.apache.royale.swc.io.SWCReader;
import org.apache.royale.swf.ITagContainer;
import org.apache.royale.swf.io.SWFReader;
import org.apache.royale.swf.tags.DoABCTag;
import org.apache.royale.swf.tags.ITag;
import org.apache.royale.swf.tags.SymbolClassTag;
/**
* Cache for parsed SWF models. The cache is a list of key-value pairs. The key
* is the URI to the SWF file. The value is a {@link SoftReference} to a
* collection of SWF tags.
*/
public class SWFCache extends ConcurrentCacheStoreBase<ITagContainer> implements ISWFCache
{
private static abstract class SWFCacheKey extends CacheStoreKeyBase
{
public SWFCacheKey()
{
}
abstract void readSWF(SWFReader swfReader) throws IOException;
}
/**
* Key object for {@code SWFCache}. It has two forms:
* <ol>
* <li>When {@code swcFile} is null, the key is an absolute path to an
* arbitrary SWF file.</li>
* <li>When {@code swcFile} is not null, the key is a URI to a library SWF
* inside a SWC file.</li>
* </ol>
*/
protected static class SWFInSWCCacheKey extends SWFCacheKey
{
protected ISWC swc; // null-able
protected String swfPath; // non-null
public SWFInSWCCacheKey()
{
}
@Override
public String generateKey()
{
return String.format("%s:%s", swc.getSWCFile().getAbsolutePath(), swfPath).intern();
}
@Override
void readSWF(SWFReader swfReader) throws IOException
{
ZipFile zipFile = null;
try
{
// Load library SWF inside a SWC.
zipFile = new ZipFile(swc.getSWCFile(), ZipFile.OPEN_READ);
InputStream swfInputStream = SWCReader.getInputStream(zipFile, swfPath);
if (swfInputStream != null)
{
swfInputStream = new BufferedInputStream(swfInputStream);
swfReader.readFrom(swfInputStream, SWCReader.getReportingPath(
swc.getSWCFile().getAbsolutePath(), swfPath));
}
else if (swc instanceof SWC)
{
((SWC)swc).addProblem(new FileInLibraryNotFoundProblem(swfPath,
swc.getSWCFile().getAbsolutePath()));
}
}
finally
{
// closes the input steam as well as the zip file.
zipFile.close();
}
}
}
/**
* Key object for {@code SWFCache}. It has two forms:
* <ol>
* <li>When {@code swcFile} is null, the key is an absolute path to an
* arbitrary SWF file.</li>
* <li>When {@code swcFile} is not null, the key is a URI to a library SWF
* inside a SWC file.</li>
* </ol>
*/
protected static class SWFFileCacheKey extends SWFCacheKey
{
private String fileName;
public SWFFileCacheKey()
{
}
@Override
public String generateKey()
{
return fileName.intern();
}
@Override
void readSWF(SWFReader swfReader) throws IOException
{
InputStream swfInputStream = new FileInputStream(fileName);
try
{
swfInputStream = new BufferedInputStream(swfInputStream);
swfReader.readFrom(swfInputStream, fileName);
}
finally
{
swfInputStream.close();
}
}
}
/**
* Factory method for creating a key object for {@code SWCCache}.
*
* @param swc SWC file (optional)
* @param swfPath path to a SWF file
* @return key
*/
public static SWFInSWCCacheKey createKey(ISWC swc, String swfPath)
{
assert swc != null;
assert swfPath != null;
final SWFInSWCCacheKey key = new SWFInSWCCacheKey();
key.swc = swc;
key.swfPath = swfPath;
return key;
}
/**
* Factory method for creating a key object for {@code SWCCache}.
*
* @param swfFileName path to a SWF file
* @return key
*/
public static SWFFileCacheKey createKey(String swfFileName)
{
final SWFFileCacheKey key = new SWFFileCacheKey();
key.fileName = swfFileName.intern();
return key;
}
/**
* Find {@code DoABC} tag by name.
*
* @param tags list of tags
* @param abcName abc name
* @return {@code DoABCTag} or null
*/
public static DoABCTag findDoABCTagByName(ITagContainer tags, String abcName)
{
assert (abcName != null && !"".equals(abcName)) : "expect ABC name.";
for (final ITag tag : tags)
{
if (tag instanceof DoABCTag)
{
final DoABCTag abcTag = (DoABCTag)tag;
if (abcTag.getName().equals(abcName))
{
return abcTag;
}
}
}
return null;
}
/**
* Find all {@code SymbolClassTag} contained in the SWF.
*
* @param tags list of tags
* @return A Collection of {@code SymbolClassTag}
*/
public static Collection<SymbolClassTag> findAllSymbolClassTags(ITagContainer tags)
{
List<SymbolClassTag> symbolTags = new ArrayList<SymbolClassTag>();
for (final ITag tag : tags)
{
if (tag instanceof SymbolClassTag)
symbolTags.add((SymbolClassTag)tag);
}
return symbolTags;
}
/**
* @param swcManager The object that manages SWC files.
*/
public SWFCache(SWCManager swcManager)
{
super();
}
/**
* Get all the tags from a SWF file.
*
* @param key {@code ICacheStoreKey} key object
* @return {@link ITagContainer} contains all the tags in the SWF file.
*/
@Override
protected ITagContainer createEntryValue(CacheStoreKeyBase key)
{
if (!(key instanceof SWFCacheKey))
throw new IllegalArgumentException("expect SWFCacheKey but got " + key.getClass().getSimpleName());
try
{
final SWFReader swfReader = new SWFReader(false); // Need not to build SWF frames.
readInputStream(swfReader, (SWFCacheKey)key);
return swfReader;
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
/**
* Read the {@code InputStream} from SWF file URI.
*
* @param swfReader {@code SWFReader} object
* @param swfCacheKey {@code SWFCacheKey} object
* @throws IOException error
*/
private void readInputStream(SWFReader swfReader, SWFCacheKey swfCacheKey) throws IOException
{
swfCacheKey.readSWF(swfReader);
}
}