| /* |
| * |
| * 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.catalog; |
| |
| import java.io.Writer; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| import java.util.Set; |
| |
| import javax.xml.stream.FactoryConfigurationError; |
| import javax.xml.stream.XMLOutputFactory; |
| import javax.xml.stream.XMLStreamException; |
| import javax.xml.stream.XMLStreamWriter; |
| |
| import org.apache.flex.compiler.common.DependencyType; |
| import org.apache.flex.swc.ISWC; |
| import org.apache.flex.swc.ISWCComponent; |
| import org.apache.flex.swc.ISWCDigest; |
| import org.apache.flex.swc.ISWCFileEntry; |
| import org.apache.flex.swc.ISWCLibrary; |
| import org.apache.flex.swc.ISWCScript; |
| import org.apache.flex.swc.ISWCVersion; |
| import com.google.common.collect.Iterables; |
| |
| /** |
| * Use {@link XMLStreamWriter} API to serialize an {@link ISWC} model to XML. |
| */ |
| public class StAXCatalogWriter implements ICatalogXMLConstants |
| { |
| |
| /** |
| * Create an catalog.xml writer. |
| * |
| * @param swc SWC model |
| * @param writer writer |
| * @throws XMLStreamException XML error |
| * @throws FactoryConfigurationError factory error |
| */ |
| public StAXCatalogWriter(final ISWC swc, final Writer writer) throws XMLStreamException, FactoryConfigurationError |
| { |
| assert swc != null : "expect SWC model"; |
| assert writer != null : "expect Writer"; |
| |
| this.swc = swc; |
| |
| final XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance(); |
| assert xmlOutputFactory != null : "Expect XMLOutputFactory implementation."; |
| this.xmlWriter = new XMLFormatter(xmlOutputFactory.createXMLStreamWriter(writer)); |
| } |
| |
| private final XMLStreamWriter xmlWriter; |
| private final ISWC swc; |
| |
| /** |
| * Write serialized XML to output. |
| * |
| * @throws XMLStreamException error |
| */ |
| public void write() throws XMLStreamException |
| { |
| xmlWriter.writeStartDocument(); // start XML |
| |
| { |
| xmlWriter.writeStartElement(TAG_SWC); |
| xmlWriter.writeAttribute(ATTR_XMLNS, XMLNS_SWC_CATALOG_9); |
| writeVersions(); |
| writeFeatures(); |
| writeComponents(); |
| writeLibraries(); |
| writeFiles(); |
| xmlWriter.writeEndElement(); |
| } |
| |
| xmlWriter.writeEndDocument(); // end XML |
| |
| xmlWriter.flush(); |
| xmlWriter.close(); |
| } |
| |
| private static final Comparator<ISWCComponent> COMPONENT_COMPARATOR = |
| new Comparator<ISWCComponent>() { |
| |
| @Override |
| public int compare(ISWCComponent o1, ISWCComponent o2) |
| { |
| return o1.getQName().compareTo(o2.getQName()); |
| } |
| }; |
| |
| private void writeComponents() throws XMLStreamException |
| { |
| Collection<ISWCComponent> componentsList = swc.getComponents(); |
| if (componentsList.isEmpty()) |
| return; |
| xmlWriter.writeStartElement(TAG_COMPONENTS); |
| ISWCComponent[] components = componentsList.toArray(new ISWCComponent[componentsList.size()]); |
| Arrays.sort(components, COMPONENT_COMPARATOR); |
| for (final ISWCComponent component : components) |
| { |
| xmlWriter.writeEmptyElement(TAG_COMPONENT); |
| if (component.getQName() != null) |
| xmlWriter.writeAttribute(ATTR_CLASS_NAME, dottedQNameToColonQName(component.getQName())); |
| if (component.getName() != null) |
| xmlWriter.writeAttribute(ATTR_NAME, component.getName()); |
| if (component.getURI() != null) |
| xmlWriter.writeAttribute(ATTR_URI, component.getURI()); |
| if (component.getIcon() != null) |
| xmlWriter.writeAttribute(ATTR_ICON, component.getIcon()); |
| if (component.getPreview() != null) |
| xmlWriter.writeAttribute(ATTR_PREVIEW, component.getPreview()); |
| } |
| xmlWriter.writeEndElement(); |
| } |
| |
| private static final Comparator<ISWCFileEntry> FILE_COMPARATOR = |
| new Comparator<ISWCFileEntry>() |
| { |
| |
| @Override |
| public int compare(ISWCFileEntry o1, ISWCFileEntry o2) |
| { |
| return o1.getPath().compareTo(o2.getPath()); |
| } |
| |
| }; |
| |
| private void writeFiles() throws XMLStreamException |
| { |
| Collection<ISWCFileEntry> filesCollection = swc.getFiles().values(); |
| if (filesCollection.isEmpty()) |
| return; |
| xmlWriter.writeStartElement(TAG_FILES); |
| ISWCFileEntry[] files = filesCollection.toArray(new ISWCFileEntry[filesCollection.size()]); |
| Arrays.sort(files, FILE_COMPARATOR); |
| for (final ISWCFileEntry file : files) |
| { |
| xmlWriter.writeEmptyElement(TAG_FILE); |
| xmlWriter.writeAttribute(ATTR_PATH, file.getPath()); |
| xmlWriter.writeAttribute(ATTR_MOD, String.valueOf(file.getLastModified())); |
| } |
| xmlWriter.writeEndElement(); |
| } |
| |
| private static final Comparator<ISWCLibrary> LIBRARY_COMPARATOR = |
| new Comparator<ISWCLibrary>() { |
| |
| @Override |
| public int compare(ISWCLibrary o1, ISWCLibrary o2) |
| { |
| return o1.getPath().compareTo(o2.getPath()); |
| } |
| }; |
| |
| private static final Comparator<ISWCScript> SCRIPT_COMPARATOR = |
| new Comparator<ISWCScript>() { |
| |
| @Override |
| public int compare(ISWCScript o1, ISWCScript o2) |
| { |
| return o1.getName().compareTo(o2.getName()); |
| } |
| }; |
| |
| private static final Comparator<ISWCDigest> DIGEST_COMPARATOR = |
| new Comparator<ISWCDigest>() { |
| |
| @Override |
| public int compare(ISWCDigest o1, ISWCDigest o2) |
| { |
| return o1.getValue().compareTo(o2.getValue()); |
| } |
| }; |
| |
| private void writeLibraries() throws XMLStreamException |
| { |
| xmlWriter.writeStartElement(TAG_LIBRARIES); |
| |
| final Collection<ISWCLibrary> librariesCollection = swc.getLibraries(); |
| final ISWCLibrary[] libraries = librariesCollection.toArray(new ISWCLibrary[librariesCollection.size()]); |
| Arrays.sort(libraries, LIBRARY_COMPARATOR); |
| |
| for (final ISWCLibrary library : libraries) |
| { |
| xmlWriter.writeStartElement(TAG_LIBRARY); |
| xmlWriter.writeAttribute(ATTR_PATH, library.getPath()); |
| { |
| final Collection<ISWCScript> scriptsList = library.getScripts(); |
| final ISWCScript[] scripts = scriptsList.toArray(new ISWCScript[scriptsList.size()]); |
| Arrays.sort(scripts, SCRIPT_COMPARATOR); |
| for (final ISWCScript script : scripts) |
| { |
| writeLibraryScript(script); |
| } |
| |
| final Collection<String> keepAS3MetadataList = library.getKeepAS3MetadataSet(); |
| if (!keepAS3MetadataList.isEmpty()) |
| { |
| xmlWriter.writeStartElement(TAG_KEEP_AS3_METADATA); |
| |
| final String[] keepAS3Metadata = keepAS3MetadataList.toArray(new String[keepAS3MetadataList.size()]); |
| Arrays.sort(keepAS3Metadata); |
| for (final String metadata : keepAS3Metadata) |
| { |
| xmlWriter.writeEmptyElement(TAG_METADATA); |
| xmlWriter.writeAttribute(ATTR_NAME, metadata); |
| } |
| xmlWriter.writeEndElement(); // end of <keep-as3-metadata> |
| } |
| |
| xmlWriter.writeStartElement(TAG_DIGESTS); |
| |
| final Collection<ISWCDigest> digestsList = library.getDigests(); |
| final ISWCDigest[] digests = digestsList.toArray(new ISWCDigest[digestsList.size()]); |
| Arrays.sort(digests, DIGEST_COMPARATOR); |
| for (final ISWCDigest digest : digests) |
| { |
| xmlWriter.writeEmptyElement(TAG_DIGEST); |
| xmlWriter.writeAttribute(ATTR_TYPE, digest.getType()); |
| xmlWriter.writeAttribute(ATTR_SIGNED, digest.isSigned() ? "true" : "false"); |
| xmlWriter.writeAttribute(TAG_VALUE, digest.getValue()); |
| } |
| xmlWriter.writeEndElement(); // end of <digests> |
| } |
| xmlWriter.writeEndElement(); // end of <library> |
| } |
| |
| xmlWriter.writeEndElement(); // end of <libraries> |
| } |
| |
| private static String dottedQNameToColonQName(String qname) |
| { |
| int lastDotIndex = qname.lastIndexOf('.'); |
| if (lastDotIndex == -1) |
| return qname; |
| final String packageName = qname.substring(0, lastDotIndex); |
| final String baseName = qname.substring(lastDotIndex + 1); |
| return packageName + ":" + baseName; |
| } |
| |
| private static final Comparator<Map.Entry<String, DependencyType>> DEPENDENCY_MAP_ENTRY_COMPARATOR = |
| new Comparator<Map.Entry<String, DependencyType>>() |
| { |
| |
| @Override |
| public int compare(Entry<String, DependencyType> arg0, Entry<String, DependencyType> arg1) |
| { |
| int result = arg0.getKey().compareTo(arg1.getKey()); |
| if (result != 0) |
| return result; |
| return arg0.getValue().ordinal() - arg1.getValue().ordinal(); |
| } |
| |
| }; |
| |
| private void writeLibraryScript(final ISWCScript script) throws XMLStreamException |
| { |
| xmlWriter.writeStartElement(TAG_SCRIPT); |
| xmlWriter.writeAttribute(ATTR_NAME, script.getName()); |
| xmlWriter.writeAttribute(ATTR_MOD, String.valueOf(script.getLastModified())); |
| if (script.getSignatureChecksum() != null) |
| xmlWriter.writeAttribute(ATTR_SIGNATURE_CHECKSUM, script.getSignatureChecksum()); |
| |
| final Set<String> definitionsSet = script.getDefinitions(); |
| final String[] definitions = definitionsSet.toArray(new String[definitionsSet.size()]); |
| Arrays.sort(definitions); |
| for (final String def : definitions) |
| { |
| xmlWriter.writeEmptyElement(TAG_DEF); |
| xmlWriter.writeAttribute(ATTR_ID, dottedQNameToColonQName(def)); |
| } |
| |
| final Set<Map.Entry<String, DependencyType>> dependenciesSet = script.getDependencies().entries(); |
| final ArrayList<Map.Entry<String, DependencyType>> dependencies = |
| new ArrayList<Map.Entry<String, DependencyType>>(dependenciesSet.size()); |
| Iterables.addAll(dependencies, dependenciesSet); |
| Collections.sort(dependencies, DEPENDENCY_MAP_ENTRY_COMPARATOR); |
| |
| |
| for (final Map.Entry<String, DependencyType> dep : dependencies) |
| { |
| xmlWriter.writeEmptyElement(TAG_DEP); |
| xmlWriter.writeAttribute(ATTR_ID, dottedQNameToColonQName(dep.getKey())); |
| xmlWriter.writeAttribute(ATTR_TYPE, String.valueOf(dep.getValue().getSymbol())); |
| } |
| |
| xmlWriter.writeEndElement(); |
| } |
| |
| private void writeFeatures() throws XMLStreamException |
| { |
| xmlWriter.writeStartElement(TAG_FEATURES); |
| { |
| // Like the pre-Falcon compiler, |
| // Falcon unconditionally writes out script dependencies. |
| xmlWriter.writeEmptyElement(TAG_FEATURE_SCRIPT_DEPS); |
| |
| if (!swc.getComponents().isEmpty()) |
| xmlWriter.writeEmptyElement(TAG_FEATURE_COMPONENTS); |
| |
| if (!swc.getFiles().isEmpty()) |
| xmlWriter.writeEmptyElement(TAG_FEATURE_FILES); |
| } |
| xmlWriter.writeEndElement(); |
| } |
| |
| private void writeVersions() throws XMLStreamException |
| { |
| final ISWCVersion version = swc.getVersion(); |
| if (version == null) |
| return; |
| |
| xmlWriter.writeStartElement(TAG_VERSIONS); |
| |
| // SWC version |
| final String swcVersion = version.getSWCVersion(); |
| if (swcVersion != null) |
| { |
| xmlWriter.writeEmptyElement(TAG_SWC); |
| xmlWriter.writeAttribute(ATTR_VERSION, swcVersion); |
| } |
| |
| // Flex version |
| final String flexVersion = version.getFlexVersion(); |
| if (flexVersion != null) |
| { |
| xmlWriter.writeEmptyElement(TAG_FLEX); |
| xmlWriter.writeAttribute(ATTR_VERSION, flexVersion); |
| |
| final String flexBuild = version.getFlexBuild(); |
| if (flexBuild != null) |
| xmlWriter.writeAttribute(ATTR_BUILD, flexBuild); |
| |
| final String flexMinSupportedVersion = version.getFlexMinSupportedVersion(); |
| if (flexMinSupportedVersion != null) |
| xmlWriter.writeAttribute(ATTR_MINIMUM_SUPPORTED_VERSION, flexMinSupportedVersion); |
| } |
| |
| // Compiler version |
| final String compilerVersion = version.getCompilerVersion(); |
| if (compilerVersion != null) |
| { |
| xmlWriter.writeEmptyElement(TAG_COMPILER); |
| |
| final String compilerName = version.getCompilerName(); |
| if (compilerName != null) |
| xmlWriter.writeAttribute(ATTR_NAME, compilerName); |
| |
| xmlWriter.writeAttribute(ATTR_VERSION, compilerVersion); |
| |
| final String compilerBuild = version.getCompilerBuild(); |
| if (compilerBuild != null) |
| xmlWriter.writeAttribute(ATTR_BUILD, compilerBuild); |
| } |
| |
| xmlWriter.writeEndElement(); |
| } |
| } |