/*
*
* 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.flex.swc.io;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.apache.flex.compiler.asdoc.IPackageDITAParser;
import org.apache.flex.compiler.problems.LibraryNotFoundProblem;
import org.apache.flex.compiler.problems.FileInLibraryIOProblem;
import org.apache.flex.compiler.problems.FileInLibraryNotFoundProblem;
import org.apache.flex.swc.ISWC;
import org.apache.flex.swc.SWC;
import org.apache.flex.swc.catalog.StAXCatalogReader;
import org.apache.flex.swc.dita.IDITAList;
/**
* Read a SWC file using Java ZIP utilities. The {@code SWCReader} owns the
* result {@linkplain ISWC} object.
*/
public class SWCReader implements ISWCReader
{
public static final String CATALOG_XML = "catalog.xml";
private static final String DITA_MANIFEST = "docs/packages.dita";
private static final String ANE_EXTENSION_XML = "META-INF/AIR/extension.xml";
/**
* Create a SWCReader from a file path.
*
* @param filename file path
*/
public SWCReader(String filename)
{
this(new File(filename), IPackageDITAParser.NIL_PARSER);
}
/**
* Create a SWCReader from a file object
*
* @param swcFile input SWC file. The file must exist or a
* FileNotFoundException is thrown.
*/
public SWCReader(File swcFile)
{
this(swcFile, IPackageDITAParser.NIL_PARSER);
}
/**
* Create a SWCReader from a file object
*
* @param swcFile input SWC file. The file must exist or a
* FileNotFoundException is thrown.
* @param packageDitaParser {@link IPackageDITAParser} that will be used to
* parse DITA information found in the SWC.
*/
public SWCReader(File swcFile, IPackageDITAParser packageDitaParser)
{
this.swcFile = swcFile;
this.swc = new SWC(swcFile);
if (!swcFile.exists() || !swcFile.isFile())
{
swc.addProblem(new LibraryNotFoundProblem(swcFile.getAbsolutePath()));
return;
}
ZipFile zipFile = null;
catalogReader = null;
try
{
try
{
zipFile = new ZipFile(swcFile, ZipFile.OPEN_READ);
final InputStream catalogInputStream = getInputStream(zipFile, CATALOG_XML);
if (catalogInputStream == null)
{
swc.addProblem(new FileInLibraryNotFoundProblem(swcFile.getAbsolutePath(), CATALOG_XML));
return;
}
catalogReader = new StAXCatalogReader(new BufferedInputStream(catalogInputStream), swc);
catalogReader.parse();
catalogReader.close();
catalogReader = null;
}
catch (Exception e)
{
swc.addProblem(new FileInLibraryIOProblem(CATALOG_XML,
swcFile.getAbsolutePath(),
e.getLocalizedMessage()));
return;
}
try
{
//might not exist, so wrap in a try catch
final InputStream ditaInputStream = getInputStream(zipFile, DITA_MANIFEST);
if(ditaInputStream != null)
{
try
{
IDITAList list = packageDitaParser.parse(swcFile.getAbsolutePath(), ditaInputStream);
if (list != null)
swc.setDITAList(list);
}
finally
{
ditaInputStream.close();
}
}
}
catch (IOException e)
{
//ignore this
}
// The swc is an considered an ANE if it contains a
// META-INF/AIR/extension.xml file.
swc.setIsANE(zipFile.getEntry(ANE_EXTENSION_XML) != null);
}
finally
{
try
{
if (catalogReader != null)
catalogReader.close();
if (zipFile != null)
zipFile.close();
}
catch (Exception e)
{
// ignore
}
}
}
private final File swcFile;
private StAXCatalogReader catalogReader;
private final SWC swc;
@Override
public File getFile()
{
return swcFile;
}
@Override
public ISWC getSWC()
{
return swc;
}
/**
* Get the {@code InputStream} of a file in the SWC archive. If the file
* does not exist in the zip file, return null.
*
* @param zipFile Zip file.
* @param filename Name of the file in the zip archive.
* @return InputStream of the file in the zip archive, or null.
* @throws IOException Error reading file from zip archive.
*/
public static InputStream getInputStream(ZipFile zipFile, String filename) throws IOException
{
ZipEntry zipEntry = null;
for (final Enumeration<? extends ZipEntry> entryEnum = zipFile.entries(); entryEnum.hasMoreElements();)
{
final ZipEntry entry = entryEnum.nextElement();
if (entry.getName().equals(filename))
{
zipEntry = entry;
break;
}
}
if (zipEntry == null)
return null;
else
return zipFile.getInputStream(zipEntry);
}
/**
* Create a single path that is a combined path of the SWC and the library
* inside. This path should only be used for error reporting. It should not
* be used to open the file.
*
* @param swcPath the path of the SWC.
* @param libraryPath the path of the library withing the SWC.
* @return combined path for SWC and library file.
*/
public static String getReportingPath(String swcPath, String libraryPath)
{
assert swcPath != null && libraryPath != null;
StringBuilder sb = new StringBuilder();
sb.append(swcPath).append("(").append(libraryPath).append(")");
return sb.toString();
}
}