http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/657a7def/flex-maven-tools/mavenizer/converters/base/src/main/java/org/apache/flex/utilities/converter/BaseConverter.java ---------------------------------------------------------------------- diff --git a/flex-maven-tools/mavenizer/converters/base/src/main/java/org/apache/flex/utilities/converter/BaseConverter.java b/flex-maven-tools/mavenizer/converters/base/src/main/java/org/apache/flex/utilities/converter/BaseConverter.java new file mode 100644 index 0000000..5d904dd --- /dev/null +++ b/flex-maven-tools/mavenizer/converters/base/src/main/java/org/apache/flex/utilities/converter/BaseConverter.java @@ -0,0 +1,426 @@ +/* + * 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.utilities.converter; + +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.WebResource; +import freemarker.template.Configuration; +import freemarker.template.Template; +import freemarker.template.TemplateExceptionHandler; +import org.apache.flex.utilities.converter.exceptions.ConverterException; +import org.apache.flex.utilities.converter.model.MavenArtifact; +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONException; +import org.codehaus.jettison.json.JSONObject; +import org.codehaus.jettison.json.JSONTokener; + +import java.io.*; +import java.math.BigInteger; +import java.net.URL; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +/** + * Created by cdutz on 11.05.2012. + */ +public abstract class BaseConverter { + + protected final Map<String, MavenArtifact> checksums = new HashMap<String, MavenArtifact>(); + + protected static final String MAVEN_CENTRAL_SHA_1_QUERY_URL = "http://search.maven.org/solrsearch/select?rows=20&wt=json&q=1:"; + // Artifactory: "http://server:port/artifactory/api/search/checksum?repos=libs-release-local&md5=04040c7c184620af0a0a8a3682a75eb7 + // Nexus: "http://repository.sonatype.org/service/local/data_index?a=04040c7c184620af0a0a8a3682a75eb7" + + protected File rootSourceDirectory; + protected File rootTargetDirectory; + + protected Configuration freemarkerConfig; + + protected BaseConverter(File rootSourceDirectory, File rootTargetDirectory) throws ConverterException { + if(rootSourceDirectory == null) { + throw new ConverterException("Air SDK directory is null."); + } + if(rootTargetDirectory == null) { + throw new ConverterException("Target directory is null."); + } + + this.rootSourceDirectory = rootSourceDirectory; + this.rootTargetDirectory = rootTargetDirectory; + + this.freemarkerConfig = new Configuration(Configuration.VERSION_2_3_22); + this.freemarkerConfig.setDefaultEncoding("UTF-8"); + this.freemarkerConfig.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); + this.freemarkerConfig.setClassForTemplateLoading(this.getClass(), "/"); + } + + public void convert() throws ConverterException { + if(rootSourceDirectory.isFile()) { + processArchive(); + } else { + processDirectory(); + } + } + + abstract protected void processDirectory() throws ConverterException; + + protected void processArchive() throws ConverterException { + + } + + protected String calculateChecksum(File jarFile) throws ConverterException { + // Implement the calculation of checksums for a given jar. + final MessageDigest digest; + try { + digest = MessageDigest.getInstance("SHA-1"); + + final InputStream is = new FileInputStream(jarFile); + final byte[] buffer = new byte[8192]; + int read; + try { + while( (read = is.read(buffer)) > 0) { + digest.update(buffer, 0, read); + } + final byte[] md5sum = digest.digest(); + final BigInteger bigInt = new BigInteger(1, md5sum); + return bigInt.toString(16); + } + catch(IOException e) { + throw new RuntimeException("Unable to process file for MD5", e); + } + finally { + try { + is.close(); + } + catch(IOException e) { + //noinspection ThrowFromFinallyBlock + throw new RuntimeException("Unable to close input stream for MD5 calculation", e); + } + } + } catch (NoSuchAlgorithmException e) { + throw new ConverterException("Error calculating checksum of file '" + jarFile.getPath() + "'", e); + } catch (FileNotFoundException e) { + throw new ConverterException("Error calculating checksum of file '" + jarFile.getPath() + "'", e); + } + } + + protected MavenArtifact lookupMetadataForChecksum(String checksum) throws ConverterException { + final String queryUrl = MAVEN_CENTRAL_SHA_1_QUERY_URL + checksum; + + final Client client = Client.create(); + final WebResource webResource = client.resource(queryUrl); + final ClientResponse response = webResource.accept("application/json").get(ClientResponse.class); + + if (response.getStatus() != 200) { + throw new RuntimeException("Failed : HTTP error code : " + response.getStatus()); + } + + final String output = response.getEntity(String.class); + + final BufferedReader reader = new BufferedReader(new StringReader(output)); + final StringBuilder builder = new StringBuilder(); + try { + for (String line; (line = reader.readLine()) != null; ) { + builder.append(line).append("\n"); + } + final JSONTokener tokener = new JSONTokener(builder.toString()); + final JSONObject rootObject = new JSONObject(tokener); + + final JSONObject responseObject = (JSONObject) rootObject.get("response"); + final int numFound = (Integer) responseObject.get("numFound"); + if(numFound == 0) { + return null; + } + else if(numFound == 1) { + final JSONArray docs = (JSONArray) responseObject.get("docs"); + final JSONObject firstHit = (JSONObject) docs.get(0); + + final MavenArtifact artifactMetadata = new MavenArtifact(); + artifactMetadata.setGroupId((String) firstHit.get("g")); + artifactMetadata.setArtifactId((String) firstHit.get("a")); + artifactMetadata.setVersion((String) firstHit.get("v")); + artifactMetadata.setPackaging((String) firstHit.get("p")); + + return artifactMetadata; + } else { + long newestTimestamp = 0; + JSONObject newestVersion = null; + + JSONArray options = (JSONArray) responseObject.get("docs"); + // if the "groupId" is "batik" then use the newer version. + for(int i = 0; i < numFound; i++) { + final JSONObject option = (JSONObject) options.get(0); + if("batik".equals(option.get("g")) && "batik-dom".equals(option.get("a")) && "jar".equals(option.get("p"))) { + final long timestamp = (Long) option.get("timestamp"); + if(timestamp > newestTimestamp) { + newestTimestamp = timestamp; + newestVersion = option; + } + } + } + + if(newestVersion != null) { + final MavenArtifact artifactMetadata = new MavenArtifact(); + artifactMetadata.setGroupId((String) newestVersion.get("g")); + artifactMetadata.setArtifactId((String) newestVersion.get("a")); + artifactMetadata.setVersion((String) newestVersion.get("v")); + artifactMetadata.setPackaging((String) newestVersion.get("p")); + + return artifactMetadata; + } else { + System.out.println("For jar-file with checksum: " + checksum + + " more than one result was returned by query: " + queryUrl); + } + } + return null; + } catch(IOException e) { + throw new ConverterException("Error processing Metadata for checksum: '" + checksum + "'", e); + } catch (JSONException e) { + throw new ConverterException("Error processing Metadata for checksum: '" + checksum + "'", e); + } + } + + protected void copyFile(File source, File target) throws ConverterException { + try { + final File outputDirectory = target.getParentFile(); + if(!outputDirectory.exists()) { + if(!outputDirectory.mkdirs()) { + throw new RuntimeException("Could not create directory: " + outputDirectory.getAbsolutePath()); + } + } + + final InputStream in = new FileInputStream(source); + final OutputStream out = new FileOutputStream(target); + + final byte[] buf = new byte[1024]; + int len; + while ((len = in.read(buf)) > 0){ + out.write(buf, 0, len); + } + + in.close(); + out.close(); + } catch(IOException e) { + throw new ConverterException("Error copying file from '" + source.getPath() + + "' to '" + target.getPath() + "'", e); + } + } + + protected void writePomArtifact(MavenArtifact pomData) throws ConverterException { + final File outputFile = pomData.getPomTargetFile(rootTargetDirectory); + createPomDocument(pomData, outputFile); + } + + protected void createPomDocument(final MavenArtifact metadata, File outputFile) throws ConverterException { + try { + // Build a context to hold the model + Map freemarkerContext = new HashMap(); + freemarkerContext.put("artifact", metadata); + + // Try to get a template "templates/{type}.vm". + Template template; + URL check = this.getClass().getClassLoader().getResource("templates/" + metadata.getPackaging() + ".ftl"); + if(check != null) { + template = freemarkerConfig.getTemplate("templates/" + metadata.getPackaging() + ".ftl"); + } else { + template = freemarkerConfig.getTemplate("templates/default.ftl"); + } + + // Prepare an output stream to which the output can be generated. + FileWriter writer = null; + try { + if(!outputFile.getParentFile().exists()) { + if(!outputFile.getParentFile().mkdirs()) { + throw new ConverterException("Could not create template output directory."); + } + } + + writer = new FileWriter(outputFile); + + // Have Freemarker generate the output for the template. + template.process(freemarkerContext, writer); + } finally { + if(writer != null) { + writer.close(); + } + } + } catch (Exception e) { + throw new ConverterException("Error generating template output.", e); + } + } + + protected void writeDummy(final File targetFile) throws ConverterException { + try { + final ZipOutputStream out = new ZipOutputStream(new FileOutputStream(targetFile)); + out.putNextEntry(new ZipEntry("dummy")); + out.closeEntry(); + out.close(); + } catch (IOException e) { + throw new ConverterException("Error generating dummy resouce bundle."); + } + } + + protected static File findDirectory(File directory, String directoryToFind) { + File[] entries = directory.listFiles(); + File founded = null; + + // Go over entries + if(entries != null) { + for (File entry : entries) { + if (entry.isDirectory() && directoryToFind.equalsIgnoreCase(entry.getName())) { + founded = entry; + break; + } + if (entry.isDirectory()) { + founded = findDirectory(entry, directoryToFind); + if (founded != null) + break; + } + } + } + return founded; + } + + protected MavenArtifact resolveArtifact(File sourceFile, String defaultGroupId, String defaultVersion) + throws ConverterException { + // Calculate a checksum for the current file. We will use this checksum to query maven central + // in order to find out if this lib has already been published. If it has, there is no need to + // publish it again under a new name. In case a matching artifact is found the generated FDK + // will use the already deployed version. Additionally the checksum will be saved and if a + // fdk generated after this one uses the same version of a lib, the version of the older fdk is + // used also reducing the amount of jars that have to be re-deployed. + final String checksum = calculateChecksum(sourceFile); + + // Try to get artifact metadata based upon the checksum by looking up the internal cache. + MavenArtifact artifact = checksums.get(checksum); + + // Reusing artifact from other sdk version. + if(artifact != null) { + System.out.println("Reusing artifact (" + checksum + ") : " + artifact.getGroupId() + ":" + + artifact.getArtifactId() + ":" + artifact.getVersion()); + return artifact; + } + // Id no artifact was found in the local cache, continue processing. + else { + // Do a lookup in maven central. + artifact = lookupMetadataForChecksum(checksum); + + // The file was available on maven central, so use that version instead of the one coming with the sdk. + if(artifact != null) { + System.out.println("Using artifact from Maven Central (" + checksum + ") : " + + artifact.getGroupId() + ":" + artifact.getArtifactId() + ":" + artifact.getVersion()); + } + // The file was not available on maven central, so we have to add it manually. + else { + // The artifact name is the name of the jar. + final String artifactFileName = sourceFile.getName(); + final String dependencyArtifactId = artifactFileName.substring(0, artifactFileName.lastIndexOf(".")); + final String dependencyArtifactPackaging = + artifactFileName.substring(artifactFileName.lastIndexOf(".") + 1); + + // Generate a new metadata object + artifact = new MavenArtifact(); + artifact.setGroupId(defaultGroupId); + artifact.setArtifactId(dependencyArtifactId); + artifact.setVersion(defaultVersion); + artifact.setPackaging(dependencyArtifactPackaging); + artifact.addDefaultBinaryArtifact(sourceFile); + + // Create the pom document that will reside next to the artifact lib. + writeArtifact(artifact); + } + + // Remember the checksum for later re-usage. + checksums.put(checksum, artifact); + + return artifact; + } + } + + protected void writeArtifact(MavenArtifact artifact) throws ConverterException { + // Write the pom itself. + writePomArtifact(artifact); + final List<String> binaryClassifiers = artifact.getBinaryFilesClassifiers(); + for(final String classifier : binaryClassifiers) { + final File binarySourceFile = artifact.getBinarySourceFile(classifier); + final File binaryTargetFile = artifact.getBinaryTargetFile(rootTargetDirectory, classifier); + copyFile(binarySourceFile, binaryTargetFile); + } + } + + protected void generateZip(File[] sourceFiles, File targetFile) throws ConverterException { + if((sourceFiles == null) || (sourceFiles.length == 0)) { + return; + } + final File rootDir = sourceFiles[0].getParentFile(); + final File zipInputFiles[] = new File[sourceFiles.length]; + System.arraycopy(sourceFiles, 0, zipInputFiles, 0, sourceFiles.length); + + try { + // Add all the content to a zip-file. + final ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(targetFile)); + for (final File file : zipInputFiles) { + addFileToZip(zipOutputStream, file, rootDir); + } + zipOutputStream.close(); + } catch(IOException e) { + throw new ConverterException("Error generating " + targetFile.getName() + " zip.", e); + } + } + + private void addFileToZip(ZipOutputStream zipOutputStream, File inputFile, File rootDirectory) + throws ConverterException { + + if (inputFile == null) { + return; + } + + // If this is a directory, add all it's children. + if (inputFile.isDirectory()) { + final File directoryContent[] = inputFile.listFiles(); + if (directoryContent != null) { + for (final File file : directoryContent) { + addFileToZip(zipOutputStream, file, rootDirectory); + } + } + } + // If this is a file, add it to the zips output. + else { + byte[] buf = new byte[1024]; + try { + final FileInputStream in = new FileInputStream(inputFile); + final String zipPath = inputFile.getAbsolutePath().substring( + rootDirectory.getAbsolutePath().length() + 1).replace("\\", "/"); + zipOutputStream.putNextEntry(new ZipEntry(zipPath)); + int len; + while ((len = in.read(buf)) > 0) { + zipOutputStream.write(buf, 0, len); + } + zipOutputStream.closeEntry(); + in.close(); + } catch(IOException e) { + throw new ConverterException("Error adding files to zip.", e); + } + } + } + +}
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/657a7def/flex-maven-tools/mavenizer/converters/base/src/main/java/org/apache/flex/utilities/converter/Converter.java ---------------------------------------------------------------------- diff --git a/flex-maven-tools/mavenizer/converters/base/src/main/java/org/apache/flex/utilities/converter/Converter.java b/flex-maven-tools/mavenizer/converters/base/src/main/java/org/apache/flex/utilities/converter/Converter.java new file mode 100644 index 0000000..54f4e18 --- /dev/null +++ b/flex-maven-tools/mavenizer/converters/base/src/main/java/org/apache/flex/utilities/converter/Converter.java @@ -0,0 +1,28 @@ +/* + * 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.utilities.converter; + +import org.apache.flex.utilities.converter.exceptions.ConverterException; + +/** + * Created by cdutz on 18.04.2014. + */ +public interface Converter { + + void convert() throws ConverterException; + +} http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/657a7def/flex-maven-tools/mavenizer/converters/base/src/main/java/org/apache/flex/utilities/converter/exceptions/ConverterException.java ---------------------------------------------------------------------- diff --git a/flex-maven-tools/mavenizer/converters/base/src/main/java/org/apache/flex/utilities/converter/exceptions/ConverterException.java b/flex-maven-tools/mavenizer/converters/base/src/main/java/org/apache/flex/utilities/converter/exceptions/ConverterException.java new file mode 100644 index 0000000..384f2fe --- /dev/null +++ b/flex-maven-tools/mavenizer/converters/base/src/main/java/org/apache/flex/utilities/converter/exceptions/ConverterException.java @@ -0,0 +1,32 @@ +/* + * 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.utilities.converter.exceptions; + +/** + * Created by cdutz on 07.05.2014. + */ +public class ConverterException extends Exception { + + public ConverterException(String message) { + super(message); + } + + public ConverterException(String message, Throwable cause) { + super(message, cause); + } + +} http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/657a7def/flex-maven-tools/mavenizer/converters/base/src/main/java/org/apache/flex/utilities/converter/model/MavenArtifact.java ---------------------------------------------------------------------- diff --git a/flex-maven-tools/mavenizer/converters/base/src/main/java/org/apache/flex/utilities/converter/model/MavenArtifact.java b/flex-maven-tools/mavenizer/converters/base/src/main/java/org/apache/flex/utilities/converter/model/MavenArtifact.java new file mode 100644 index 0000000..018542a --- /dev/null +++ b/flex-maven-tools/mavenizer/converters/base/src/main/java/org/apache/flex/utilities/converter/model/MavenArtifact.java @@ -0,0 +1,168 @@ +/* + * 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.utilities.converter.model; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Created by cdutz on 01.07.2012. + */ +public class MavenArtifact { + + public static final String DEFAULT_CLASSIFIER = "default"; + + protected String groupId; + protected String artifactId; + protected String version; + protected String packaging = "pom"; + protected String classifier; + protected List<String> librariesWithResourceBundles; + + protected List<MavenArtifact> dependencies; + + protected Map<String, File> binaryArtifacts; + + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public String getArtifactId() { + return artifactId; + } + + public void setArtifactId(String artifactId) { + this.artifactId = artifactId; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getPackaging() { + return packaging; + } + + public void setPackaging(String packaging) { + this.packaging = packaging; + } + + public String getClassifier() { + return classifier; + } + + public void setClassifier(String classifier) { + this.classifier = classifier; + } + + public List<String> getLibrariesWithResourceBundles() { + return librariesWithResourceBundles; + } + + public void setLibrariesWithResourceBundles(List<String> librariesWithResourceBundles) { + this.librariesWithResourceBundles = librariesWithResourceBundles; + } + + public List<MavenArtifact> getDependencies() { + return dependencies; + } + + public void setDependencies(List<MavenArtifact> dependencies) { + this.dependencies = dependencies; + } + + public void addDependency(MavenArtifact dependency) { + if(dependencies == null) { + dependencies = new ArrayList<MavenArtifact>(); + } + dependencies.add(dependency); + } + + public void addDefaultBinaryArtifact(File binaryArtifact) { + addBinaryArtifact(DEFAULT_CLASSIFIER, binaryArtifact); + } + + public void addBinaryArtifact(String classifier, File binaryArtifact) { + if(binaryArtifacts == null) { + binaryArtifacts = new HashMap<String, File>(); + } + binaryArtifacts.put(classifier, binaryArtifact); + } + + public boolean hasBinaryArtifact(String classifier) { + return binaryArtifacts != null && binaryArtifacts.containsKey(classifier); + } + + public File getPomTargetFile(File targetRootDirectory) { + final String fileName = groupId.replace(".", File.separator) + File.separator + artifactId + File.separator + + version + File.separator + artifactId + "-" + version + ((classifier != null) ? "-" + classifier : "") + + ".pom"; + return new File(targetRootDirectory, fileName); + } + + public List<String> getBinaryFilesClassifiers() { + final List<String> classifiers = new ArrayList<String>(); + if(binaryArtifacts != null) { + classifiers.addAll(binaryArtifacts.keySet()); + } + return classifiers; + } + + public File getBinarySourceFile(String classifier) { + if((binaryArtifacts != null) && (binaryArtifacts.containsKey(classifier))) { + return binaryArtifacts.get(classifier); + } + return null; + } + + public File getBinaryTargetFile(File targetRootDirectory, String classifier) { + if((binaryArtifacts != null) && (binaryArtifacts.containsKey(classifier))) { + final String fileName = groupId.replace(".", File.separator) + File.separator + artifactId + File.separator + + version + File.separator + artifactId + "-" + version + + (DEFAULT_CLASSIFIER.equals(classifier) ? "" : "-" + classifier) + "." + packaging; + return new File(targetRootDirectory, fileName); + } + return null; + } + + public boolean hasDependencies() { + return (dependencies != null) && (!dependencies.isEmpty()); + } + + public boolean isAtLeastOneDependencyRsl() { + if(dependencies != null) { + for(final MavenArtifact dependency : dependencies) { + if(dependency.hasBinaryArtifact("rsl")) { + return true; + } + } + } + return false; + } + +} http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/657a7def/flex-maven-tools/mavenizer/converters/base/src/main/resources/templates/default.ftl ---------------------------------------------------------------------- diff --git a/flex-maven-tools/mavenizer/converters/base/src/main/resources/templates/default.ftl b/flex-maven-tools/mavenizer/converters/base/src/main/resources/templates/default.ftl new file mode 100644 index 0000000..e4a200b --- /dev/null +++ b/flex-maven-tools/mavenizer/converters/base/src/main/resources/templates/default.ftl @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- + + 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. + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0"> + <modelVersion>4.0.0</modelVersion> + + <groupId>${artifact.groupId}</groupId> + <artifactId>${artifact.artifactId}</artifactId> + <version>${artifact.version}</version> + <packaging>${artifact.packaging}</packaging> + +<#if artifact.hasDependencies()> + <dependencies> +<#list artifact.dependencies as dependency> + <dependency> + <groupId>${dependency.groupId}</groupId> + <artifactId>${dependency.artifactId}</artifactId> + <version>${dependency.version}</version> + <type>${dependency.packaging}</type> + </dependency> +</#list> + </dependencies> +</#if> + +</project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/657a7def/flex-maven-tools/mavenizer/converters/base/src/main/resources/templates/pom.ftl ---------------------------------------------------------------------- diff --git a/flex-maven-tools/mavenizer/converters/base/src/main/resources/templates/pom.ftl b/flex-maven-tools/mavenizer/converters/base/src/main/resources/templates/pom.ftl new file mode 100644 index 0000000..1242fb7 --- /dev/null +++ b/flex-maven-tools/mavenizer/converters/base/src/main/resources/templates/pom.ftl @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- + + 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. + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0"> + <modelVersion>4.0.0</modelVersion> + + <groupId>${artifact.groupId}</groupId> + <artifactId>${artifact.artifactId}</artifactId> + <version>${artifact.version}</version> + <packaging>${artifact.packaging}</packaging> + +<#if artifact.hasDependencies()> + <dependencies> +<#list artifact.dependencies as dependency> + <dependency> + <groupId>${dependency.groupId}</groupId> + <artifactId>${dependency.artifactId}</artifactId> + <version>${dependency.version}</version> +<#if dependency.packaging != "jar"> + <type>${dependency.packaging}</type> +</#if> + </dependency> +</#list> + </dependencies> + + <dependencyManagement> + <dependencies> +<#list artifact.dependencies as dependency> + <dependency> + <groupId>${dependency.groupId}</groupId> + <artifactId>${dependency.artifactId}</artifactId> + <version>${dependency.version}</version> + </dependency> +</#list> + </dependencies> + </dependencyManagement> +</#if> + +</project> http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/657a7def/flex-maven-tools/mavenizer/converters/flash/pom.xml ---------------------------------------------------------------------- diff --git a/flex-maven-tools/mavenizer/converters/flash/pom.xml b/flex-maven-tools/mavenizer/converters/flash/pom.xml new file mode 100644 index 0000000..6afc519 --- /dev/null +++ b/flex-maven-tools/mavenizer/converters/flash/pom.xml @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + 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. + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.flex.utilities.converter</groupId> + <artifactId>converters</artifactId> + <version>1.0.0-SNAPSHOT</version> + </parent> + + <artifactId>flash-converter</artifactId> + <version>1.0.0-SNAPSHOT</version> + <packaging>jar</packaging> + + <dependencies> + <dependency> + <groupId>org.apache.flex.utilities.converter</groupId> + <artifactId>base-converter</artifactId> + <version>1.0.0-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-compress</artifactId> + <version>1.4</version> + </dependency> + </dependencies> + +</project> http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/657a7def/flex-maven-tools/mavenizer/converters/flash/src/main/java/org/apache/flex/utilities/converter/flash/FlashConverter.java ---------------------------------------------------------------------- diff --git a/flex-maven-tools/mavenizer/converters/flash/src/main/java/org/apache/flex/utilities/converter/flash/FlashConverter.java b/flex-maven-tools/mavenizer/converters/flash/src/main/java/org/apache/flex/utilities/converter/flash/FlashConverter.java new file mode 100644 index 0000000..776e0c6 --- /dev/null +++ b/flex-maven-tools/mavenizer/converters/flash/src/main/java/org/apache/flex/utilities/converter/flash/FlashConverter.java @@ -0,0 +1,286 @@ +/* + * 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.utilities.converter.flash; + +import org.apache.commons.compress.archivers.ArchiveEntry; +import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; +import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; +import org.apache.flex.utilities.converter.BaseConverter; +import org.apache.flex.utilities.converter.Converter; +import org.apache.flex.utilities.converter.exceptions.ConverterException; +import org.apache.flex.utilities.converter.model.MavenArtifact; + +import java.io.*; +import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; + +/** + * Created by cdutz on 22.04.2014. + */ +public class FlashConverter extends BaseConverter implements Converter { + + /** + * @param rootSourceDirectory Path to the root of the original Flash SDK. + * @param rootTargetDirectory Path to the root of the directory where the Maven artifacts should be generated to. + * @throws org.apache.flex.utilities.converter.exceptions.ConverterException + */ + public FlashConverter(File rootSourceDirectory, File rootTargetDirectory) throws ConverterException { + super(rootSourceDirectory, rootTargetDirectory); + } + + /** + * Entry point for generating the Maven artifacts for an Flash SDK. + * + * @throws ConverterException + */ + @Override + protected void processDirectory() throws ConverterException { + if(!rootSourceDirectory.exists() || !rootSourceDirectory.isDirectory()) { + System.out.println("Skipping Flash SDK generation."); + return; + } + + generateRuntimeArtifacts(); + generateFrameworkArtifacts(); + } + + /** + * This method generates those artifacts that resemble the runtime part of the Flash SDK. + * + * @throws ConverterException + */ + protected void generateRuntimeArtifacts() throws ConverterException { + // Create a list of all libs that should belong to the Flash SDK runtime. + final File directory = new File(rootSourceDirectory, "runtimes" + File.separator + "player"); + if(!directory.exists() || !directory.isDirectory()) { + System.out.println("Skipping Flash runtime generation."); + return; + } + final List<File> playerVersions = new ArrayList<File>(); + playerVersions.addAll(Arrays.asList(directory.listFiles(new FlashRuntimeFilter()))); + + // In really old SDKs the flash-player was installed in the players directory directly. + if(new File(directory, "win").exists()) { + playerVersions.add(directory); + } + + // Generate artifacts for every jar in the input directories. + for(final File versionDir : playerVersions) { + // The flash-player 9 is installed directly in the player directory. + String playerVersionString; + if(versionDir == directory) { + playerVersionString = "9.0"; + } else { + playerVersionString = versionDir.getName(); + } + + final double playerVersion = Double.valueOf(playerVersionString); + final NumberFormat doubleFormat = NumberFormat.getInstance(Locale.US); + doubleFormat.setMinimumFractionDigits(1); + doubleFormat.setMaximumFractionDigits(1); + final String version = doubleFormat.format(playerVersion); + + final MavenArtifact playerArtifact = new MavenArtifact(); + playerArtifact.setGroupId("com.adobe.flash"); + playerArtifact.setArtifactId("runtime"); + playerArtifact.setVersion(version); + playerArtifact.setPackaging("exe"); + + // Deploy Windows binaries. + final File windowsDirectory = new File(versionDir, "win"); + if(windowsDirectory.exists()) { + // Find out if a flash-player binary exists. + File flashPlayerBinary = null; + if(new File(windowsDirectory, "FlashPlayerDebugger.exe").exists()) { + flashPlayerBinary = new File(windowsDirectory, "FlashPlayerDebugger.exe"); + } else if(new File(windowsDirectory, "FlashPlayer.exe").exists()) { + flashPlayerBinary = new File(windowsDirectory, "FlashPlayer.exe"); + } + + // If a binary exists, copy it to the target and create a pom for it. + if (flashPlayerBinary != null) { + playerArtifact.addBinaryArtifact("win", flashPlayerBinary); + } + } + + // Deploy Mac binaries. + final File macDirectory = new File(versionDir, "mac"); + if(macDirectory.exists()) { + // Find out if a flash-player binary exists. + File flashPlayerBinary = null; + if(new File(macDirectory, "Flash Player.app.zip").exists()) { + flashPlayerBinary = new File(macDirectory, "Flash Player.app.zip"); + } else if(new File(macDirectory, "Flash Player Debugger.app.zip").exists()) { + flashPlayerBinary = new File(macDirectory, "Flash Player Debugger.app.zip"); + } + + // If a binary exists, copy it to the target and create a pom for it. + if (flashPlayerBinary != null) { + playerArtifact.addBinaryArtifact("mac", flashPlayerBinary); + } + } + + // Deploy Linux binaries. + final File lnxDirectory = new File(versionDir, "lnx"); + if(lnxDirectory.exists()) { + // Find out if a flash-player binary exists. + File flashPlayerBinary; + if(new File(lnxDirectory, "flashplayer.tar.gz").exists()) { + flashPlayerBinary = new File(lnxDirectory, "flashplayer.tar.gz"); + } else if(new File(lnxDirectory, "flashplayerdebugger.tar.gz").exists()) { + flashPlayerBinary = new File(lnxDirectory, "flashplayerdebugger.tar.gz"); + } else { + throw new ConverterException("Couldn't find player archive."); + } + + // Decompress the archive. + // First unzip it. + final FileInputStream fin; + try { + fin = new FileInputStream(flashPlayerBinary); + final BufferedInputStream in = new BufferedInputStream(fin); + final File tempTarFile = File.createTempFile("flex-sdk-linux-flashplayer-binary-" + version, ".tar"); + final FileOutputStream out = new FileOutputStream(tempTarFile); + final GzipCompressorInputStream gzIn = new GzipCompressorInputStream(in); + final byte[] buffer = new byte[1024]; + int n; + while (-1 != (n = gzIn.read(buffer))) { + out.write(buffer, 0, n); + } + out.close(); + gzIn.close(); + + // Then untar it. + File uncompressedBinary = null; + final FileInputStream tarFileInputStream = new FileInputStream(tempTarFile); + final TarArchiveInputStream tarArchiveInputStream = new TarArchiveInputStream(tarFileInputStream); + ArchiveEntry entry; + while((entry = tarArchiveInputStream.getNextEntry()) != null) { + if("flashplayer".equals(entry.getName())) { + uncompressedBinary = File.createTempFile("flex-sdk-linux-flashplayer-binary-" + version, ".uexe"); + final FileOutputStream uncompressedBinaryOutputStream = new FileOutputStream(uncompressedBinary); + while(-1 != (n = tarArchiveInputStream.read(buffer))) { + uncompressedBinaryOutputStream.write(buffer, 0, n); + } + uncompressedBinaryOutputStream.close(); + } else if("flashplayerdebugger".equals(entry.getName())) { + uncompressedBinary = File.createTempFile("flex-sdk-linux-flashplayer-binary-" + version, ".uexe"); + final FileOutputStream uncompressedBinaryOutputStream = new FileOutputStream(uncompressedBinary); + while(-1 != (n = tarArchiveInputStream.read(buffer))) { + uncompressedBinaryOutputStream.write(buffer, 0, n); + } + uncompressedBinaryOutputStream.close(); + } + } + tarFileInputStream.close(); + + // If a binary exists, copy it to the target and create a pom for it. + if (uncompressedBinary != null) { + playerArtifact.addBinaryArtifact("linux", flashPlayerBinary); + } + } catch (FileNotFoundException e) { + throw new ConverterException("Error processing the linux player tar file", e); + } catch (IOException e) { + throw new ConverterException("Error processing the linux player tar file", e); + } + } + + // Write this artifact to file. + writeArtifact(playerArtifact); + } + } + + /** + * This method generates those artifacts that resemble the framework part of the Flash SDK. + * + * @throws ConverterException + */ + protected void generateFrameworkArtifacts() throws ConverterException { + // Create a list of all libs that should belong to the Flash SDK runtime. + final File directory = new File(rootSourceDirectory, "frameworks.libs.player".replace(".", File.separator)); + // It seems the fdk directory doesn't contain any flash resources. + if (!directory.exists() || !directory.isDirectory()) { + System.out.println("Skipping Flash framework generation."); + return; + } + final List<File> playerVersions = new ArrayList<File>(); + final File[] versions = directory.listFiles(); + if((versions != null) && (versions.length > 0)) { + playerVersions.addAll(Arrays.asList(versions)); + + // Generate artifacts for every jar in the input directories. + for (final File versionDir : playerVersions) { + final File playerglobalSwc = new File(versionDir, "playerglobal.swc"); + + // Convert any version into a two-segment version number. + final double playerVersion = Double.valueOf(versionDir.getName()); + final NumberFormat doubleFormat = NumberFormat.getInstance(Locale.US); + doubleFormat.setMinimumFractionDigits(1); + doubleFormat.setMaximumFractionDigits(1); + final String version = doubleFormat.format(playerVersion); + + // Create an artifact for the player-global. + final MavenArtifact playerglobal = new MavenArtifact(); + playerglobal.setGroupId("com.adobe.flash.framework"); + playerglobal.setArtifactId("playerglobal"); + playerglobal.setVersion(version); + playerglobal.setPackaging("swc"); + playerglobal.addDefaultBinaryArtifact(playerglobalSwc); + writeArtifact(playerglobal); + + // Create a dummy pom artifact that references the playerglobal + // in order to consequently have a framework artifact for every + // part of flex. + final MavenArtifact framework = new MavenArtifact(); + framework.setGroupId("com.adobe.flash"); + framework.setArtifactId("framework"); + framework.setVersion(version); + framework.setPackaging("pom"); + framework.addDependency(playerglobal); + writePomArtifact(framework); + } + } + } + + /////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Utility methods + // + /////////////////////////////////////////////////////////////////////////////////////////////////// + + public static class FlashRuntimeFilter implements FileFilter { + public boolean accept(File pathname) { + return pathname.isDirectory() && !"win".equalsIgnoreCase(pathname.getName()) && + !"lnx".equalsIgnoreCase(pathname.getName()) && !"mac".equalsIgnoreCase(pathname.getName()); + } + } + + public static class FlashFrameworkFilter implements FilenameFilter { + public boolean accept(File dir, String name) { + return name.equals("playerglobal.swc"); + } + } + + public static void main(String[] args) throws Exception { + FlashConverter converter = new FlashConverter(new File(args[0]), new File(args[1])); + converter.convert(); + } + +} http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/657a7def/flex-maven-tools/mavenizer/converters/flex/pom.xml ---------------------------------------------------------------------- diff --git a/flex-maven-tools/mavenizer/converters/flex/pom.xml b/flex-maven-tools/mavenizer/converters/flex/pom.xml new file mode 100644 index 0000000..480bc83 --- /dev/null +++ b/flex-maven-tools/mavenizer/converters/flex/pom.xml @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + 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. + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.flex.utilities.converter</groupId> + <artifactId>converters</artifactId> + <version>1.0.0-SNAPSHOT</version> + </parent> + + <artifactId>flex-converter</artifactId> + <version>1.0.0-SNAPSHOT</version> + <packaging>jar</packaging> + + <dependencies> + <dependency> + <groupId>org.apache.flex.utilities.converter</groupId> + <artifactId>base-converter</artifactId> + <version>1.0.0-SNAPSHOT</version> + </dependency> + <!-- + Flex usually contains Air and Flash artifacts, so we need to reference them. + --> + <dependency> + <groupId>org.apache.flex.utilities.converter</groupId> + <artifactId>air-converter</artifactId> + <version>1.0.0-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.flex.utilities.converter</groupId> + <artifactId>flash-converter</artifactId> + <version>1.0.0-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.flex.utilities.converter</groupId> + <artifactId>fontkit-converter</artifactId> + <version>1.0.0-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.flex.utilities.converter</groupId> + <artifactId>wrapper-converter</artifactId> + <version>1.0.0-SNAPSHOT</version> + </dependency> + </dependencies> + +</project> http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/657a7def/flex-maven-tools/mavenizer/converters/flex/src/main/java/org/apache/flex/utilities/converter/flex/FlexConverter.java ---------------------------------------------------------------------- diff --git a/flex-maven-tools/mavenizer/converters/flex/src/main/java/org/apache/flex/utilities/converter/flex/FlexConverter.java b/flex-maven-tools/mavenizer/converters/flex/src/main/java/org/apache/flex/utilities/converter/flex/FlexConverter.java new file mode 100644 index 0000000..6def8a1 --- /dev/null +++ b/flex-maven-tools/mavenizer/converters/flex/src/main/java/org/apache/flex/utilities/converter/flex/FlexConverter.java @@ -0,0 +1,735 @@ +/* + * 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.utilities.converter.flex; + +import org.apache.flex.utilities.converter.BaseConverter; +import org.apache.flex.utilities.converter.Converter; +import org.apache.flex.utilities.converter.air.AirConverter; +import org.apache.flex.utilities.converter.exceptions.ConverterException; +import org.apache.flex.utilities.converter.flash.FlashConverter; +import org.apache.flex.utilities.converter.model.MavenArtifact; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import java.io.*; +import java.util.*; +import java.util.jar.JarOutputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +/** + * Created by cdutz on 22.04.2014. + */ +public class FlexConverter extends BaseConverter implements Converter { + + protected String flexSdkVersion; + protected String flexBuild; + + /** + * @param rootSourceDirectory Path to the root of the original Flex SDK. + * @param rootTargetDirectory Path to the root of the directory where the Maven artifacts should be generated to. + * @throws org.apache.flex.utilities.converter.exceptions.ConverterException + */ + public FlexConverter(File rootSourceDirectory, File rootTargetDirectory) throws ConverterException { + super(rootSourceDirectory, rootTargetDirectory); + + // Get the version of the current Flex SDK. + this.flexSdkVersion = getFlexVersion(rootSourceDirectory); + this.flexBuild = getFlexBuild(rootSourceDirectory); + } + + /** + * Entry point for generating the Maven artifacts for an Flex SDK. + * + * @throws ConverterException + */ + @Override + protected void processDirectory() throws ConverterException { + if((flexSdkVersion == null) || !rootSourceDirectory.exists() || !rootSourceDirectory.isDirectory()) { + System.out.println("Skipping Flex SDK generation."); + return; + } + + generateCompilerArtifacts(); + generateFrameworkArtifacts(); + } + + /** + * This method generates those artifacts that resemble the compiler part of the Flex SDK. + * + * @throws ConverterException + */ + protected void generateCompilerArtifacts() throws ConverterException { + // Create the root artifact. + final MavenArtifact compiler = new MavenArtifact(); + compiler.setGroupId("org.apache.flex"); + compiler.setArtifactId("compiler"); + compiler.setVersion(flexSdkVersion); + compiler.setPackaging("pom"); + + // Create a list of all libs that should belong to the Flex SDK compiler. + final File directory = new File(rootSourceDirectory, "lib"); + if(!directory.exists() || !directory.isDirectory()) { + throw new ConverterException("Compiler directory does not exist."); + } + final List<File> files = new ArrayList<File>(); + files.addAll(Arrays.asList(directory.listFiles(new FlexCompilerFilter()))); + + // Add all jars in the "external" directory. + final File externalDirectory = new File(directory, "external"); + if(externalDirectory.exists() && externalDirectory.isDirectory()) { + files.addAll(Arrays.asList(externalDirectory.listFiles(new FlexCompilerFilter()))); + } + + // Generate artifacts for every jar in the input directories. + for(final File sourceFile : files) { + final MavenArtifact artifact = resolveArtifact(sourceFile, "org.apache.flex.compiler", flexSdkVersion); + compiler.addDependency(artifact); + } + + // Write this artifact to file. + writeArtifact(compiler); + } + + /** + * This method generates those artifacts that resemble the framework part of the Flex SDK. + * + * @throws ConverterException + */ + protected void generateFrameworkArtifacts() throws ConverterException { + final File directory = new File(rootSourceDirectory, "frameworks" + File.separator + "libs"); + generateFrameworkArtifacts(directory, "org.apache.flex"); + generateThemeArtifacts(); + generateFrameworkConfigurationArtifact(); + } + + protected void generateFrameworkArtifacts(File directory, String curGroupId) throws ConverterException { + // Create the root artifact. + final MavenArtifact framework = new MavenArtifact(); + framework.setGroupId(curGroupId); + framework.setArtifactId("libs".equals(directory.getName()) ? "framework" : directory.getName()); + framework.setVersion(flexSdkVersion); + framework.setPackaging("pom"); + + final String artifactGroupId = framework.getGroupId() + "." + framework.getArtifactId(); + + // Create a list of all libs that should belong to the Flex SDK framework. + if(!directory.exists() || !directory.isDirectory()) { + throw new ConverterException("Framework directory does not exist."); + } + final List<File> files = new ArrayList<File>(); + files.addAll(Arrays.asList(directory.listFiles(new FlexFrameworkFilter()))); + + // Generate artifacts for every jar in the input directories. + for(final File sourceFile : files) { + // I think the experimental_mobile.swc belongs in the "mobile" package. + if(!"libs".equals(directory.getName()) || !"experimental_mobile.swc".equals(sourceFile.getName())) { + final MavenArtifact artifact = resolveArtifact(sourceFile, artifactGroupId, flexSdkVersion); + framework.addDependency(artifact); + } + } + + // Forcefully add the mx library to the rest of the framework. + if("libs".equals(directory.getName())) { + final File mxSwc = new File(directory, "mx/mx.swc"); + final MavenArtifact artifact = resolveArtifact(mxSwc, artifactGroupId, flexSdkVersion); + framework.addDependency(artifact); + } + + // If we are in the "mobile" directory and the paren contains an "experimental_mobile.swc" file, + // add this to the mobile package. + if("mobile".equals(directory.getName())) { + final File mobileExperimental = new File(directory.getParent(), "experimental_mobile.swc"); + if(mobileExperimental.exists()) { + final MavenArtifact artifact = resolveArtifact(mobileExperimental, artifactGroupId, flexSdkVersion); + framework.addDependency(artifact); + } + } + // Write this artifact to file. + writeArtifact(framework); + + // After processing the current directory, process any eventually existing child directories. + final List<File> children = new ArrayList<File>(); + children.addAll(Arrays.asList(directory.listFiles(new FileFilter() { + public boolean accept(File pathname) { + return pathname.isDirectory() && !"player".equals(pathname.getName()) && + !"mx".equals(pathname.getName()); + } + }))); + for(final File childDirectory : children) { + generateFrameworkArtifacts(childDirectory, artifactGroupId); + } + } + + protected void generateThemeArtifacts() throws ConverterException { + final File frameworksDirectory = new File(rootSourceDirectory, "frameworks"); + + // Deploy all the swcs in the themes directory. + final File themesSrcDirectory = new File(frameworksDirectory, "themes"); + if(themesSrcDirectory.exists()) { + generateDefaultThemeArtifacts(themesSrcDirectory); + } + + // Deploy MXFTEText theme + final File mxfteThemeCss = new File(frameworksDirectory, "projects" + File.separator + "spark" + + File.separator + "MXFTEText.css"); + if(mxfteThemeCss.exists()){ + generateMxFteThemeArtifact(mxfteThemeCss); + } + } + + /////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Utility methods + // + /////////////////////////////////////////////////////////////////////////////////////////////////// + + @Override + protected void writeArtifact(MavenArtifact artifact) throws ConverterException { + if(!"pom".equals(artifact.getPackaging())) { + // Copy the rsls. + final File rslSourceFile = getRsl(artifact.getArtifactId()); + if(rslSourceFile != null) { + final File rslTargetFile = new File( + artifact.getBinaryTargetFile(rootTargetDirectory, MavenArtifact.DEFAULT_CLASSIFIER).getParent(), + artifact.getArtifactId() + "-" + artifact.getVersion() + ".swf"); + copyFile(rslSourceFile, rslTargetFile); + artifact.addBinaryArtifact("rsl", rslSourceFile); + } + + // Copy the swzc. + final File signedRslSourceFile = getSignedRsl(artifact.getArtifactId()); + if(signedRslSourceFile != null) { + final File signedRslTargetFile = new File( + artifact.getBinaryTargetFile(rootTargetDirectory, MavenArtifact.DEFAULT_CLASSIFIER).getParent(), + artifact.getArtifactId() + "-" + artifact.getVersion() + ".swz"); + copyFile(signedRslSourceFile, signedRslTargetFile); + artifact.addBinaryArtifact("caching", rslSourceFile); + } + + // Copy the language resources. + final Map<String, File> resourceBundles = getResourceBundles(artifact.getArtifactId()); + if(!resourceBundles.isEmpty() && + artifact.getBinaryTargetFile(rootTargetDirectory, MavenArtifact.DEFAULT_CLASSIFIER) != null) { + boolean foundResources = false; + for(final String resource : resourceBundles.keySet()) { + final File resourceSourceFile = resourceBundles.get(resource); + final File resourceTargetFile = new File( + artifact.getBinaryTargetFile(rootTargetDirectory, MavenArtifact.DEFAULT_CLASSIFIER).getParent(), + artifact.getArtifactId() + "-" + artifact.getVersion() + "-" + resource + ".rb.swc"); + copyFile(resourceSourceFile, resourceTargetFile); + foundResources = true; + } + + // If the library had at least one resource bundle, generate a dummy rb.swc and add that as dependency. + if(foundResources) { + final File resourceDummyTargetFile = new File( + artifact.getBinaryTargetFile(rootTargetDirectory, MavenArtifact.DEFAULT_CLASSIFIER).getParent(), + artifact.getArtifactId() + "-" + artifact.getVersion() + ".rb.swc"); + writeDummy(resourceDummyTargetFile); + + final MavenArtifact resourceBundleDependency = new MavenArtifact(); + resourceBundleDependency.setGroupId(artifact.getGroupId()); + resourceBundleDependency.setArtifactId(artifact.getArtifactId()); + resourceBundleDependency.setVersion(artifact.getVersion()); + resourceBundleDependency.setPackaging("rb.swc"); + artifact.addDependency(resourceBundleDependency); + } + } + + // Add source zips. + final File sourceArtifactSourceFile = generateSourceArtifact(artifact.getArtifactId()); + if(sourceArtifactSourceFile != null) { + final File sourceArtifactTargetFile = new File( + artifact.getBinaryTargetFile(rootTargetDirectory, MavenArtifact.DEFAULT_CLASSIFIER).getParent(), + artifact.getArtifactId() + "-" + artifact.getVersion() + "-sources.jar"); + copyFile(sourceArtifactSourceFile, sourceArtifactTargetFile); + } + + // If this is the asdoc artifact, create the templates.zip for that. + if("asdoc".equals(artifact.getArtifactId())) { + final File asdocTemplatesZipSourceFile = generateAsdocTemplatesZip(); + if (asdocTemplatesZipSourceFile != null) { + final File asdocTemplatesZipTargetFile = new File( + artifact.getBinaryTargetFile( + rootTargetDirectory, MavenArtifact.DEFAULT_CLASSIFIER).getParent(), + artifact.getArtifactId() + "-" + artifact.getVersion() + "-template.zip"); + copyFile(asdocTemplatesZipSourceFile, asdocTemplatesZipTargetFile); + } + } + } + + super.writeArtifact(artifact); + } + + protected File generateSourceArtifact(String artifactId) throws ConverterException { + final File frameworksDirectory = new File(rootSourceDirectory, "frameworks"); + final File librarySrcRootPath = new File(frameworksDirectory, "projects/" + artifactId); + final File librarySourcePath = new File(librarySrcRootPath, "src"); + + if (librarySourcePath.listFiles() != null) { + final File sourceFiles[] = librarySourcePath.listFiles(); + if (sourceFiles != null) { + final File zipInputFiles[] = new File[sourceFiles.length + 1]; + System.arraycopy(sourceFiles, 0, zipInputFiles, 0, sourceFiles.length); + + try { + // Create a temp file. + final File targetFile = File.createTempFile("temp-" + artifactId, "zip"); + + JarOutputStream jar = new JarOutputStream(new FileOutputStream(targetFile)); + for (final File file : zipInputFiles) { + addFileToZip(jar, file, librarySourcePath); + } + jar.close(); + + return targetFile; + } catch(IOException e) { + throw new ConverterException("Error creating source archive.", e); + } + } + } + return null; + } + + protected File generateAsdocTemplatesZip() throws ConverterException { + final File templatesDirectory = new File(rootSourceDirectory, "asdoc/templates"); + + if (templatesDirectory.listFiles() != null) { + final File sourceFiles[] = templatesDirectory.listFiles(); + if (sourceFiles != null) { + final File zipInputFiles[] = new File[sourceFiles.length + 1]; + System.arraycopy(sourceFiles, 0, zipInputFiles, 0, sourceFiles.length); + + try { + // Create a temp file. + final File targetFile = File.createTempFile("temp-asdoc-templates", "zip"); + + JarOutputStream jar = new JarOutputStream(new FileOutputStream(targetFile)); + for (final File file : zipInputFiles) { + addFileToZip(jar, file, templatesDirectory); + } + jar.close(); + + return targetFile; + } catch(IOException e) { + throw new ConverterException("Error creating asdoc-templates archive.", e); + } + } + } + return null; + } + + protected void generateFrameworkConfigurationArtifact() throws ConverterException { + // ZIP up every file (not directory) in the framework directory and the entire themes directory. + final File frameworksDirectory = new File(rootSourceDirectory, "frameworks"); + final File sourceFiles[] = frameworksDirectory.listFiles(new FileFilter() { + public boolean accept(File pathname) { + return pathname.isFile(); + } + }); + final File zipInputFiles[] = new File[sourceFiles.length]; + System.arraycopy(sourceFiles, 0, zipInputFiles, 0, sourceFiles.length); + + try { + final File targetFile = new File(rootTargetDirectory, + "org.apache.flex.framework.framework.".replace(".", File.separator) + flexSdkVersion + + File.separator + "framework-" + flexSdkVersion + "-configs.zip"); + + // Add all the content to a zip-file. + final ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(targetFile)); + for (final File file : zipInputFiles) { + addFileToZip(zipOutputStream, file, frameworksDirectory); + } + zipOutputStream.close(); + } catch(IOException e) { + throw new ConverterException("Error generating configuration zip.", e); + } + } + + protected void generateDefaultThemeArtifacts(File themesDirectory) throws ConverterException { + final File[] themes = themesDirectory.listFiles(); + if(themes != null) { + for(final File themeDirectory : themes) { + if(themeDirectory.isDirectory()) { + final String themeName = themeDirectory.getName().toLowerCase(); + final File themeFile = new File(themeDirectory, themeName + ".swc"); + + final File targetSwcFile; + if(themeFile.exists()) { + targetSwcFile = themeFile; + } else { + targetSwcFile = generateThemeSwc(themeDirectory); + } + + if(targetSwcFile != null) { + // Generate the pom file. + final MavenArtifact themeArtifact = new MavenArtifact(); + themeArtifact.setGroupId("org.apache.flex.framework.themes"); + themeArtifact.setArtifactId(themeName); + themeArtifact.setVersion(flexSdkVersion); + themeArtifact.setPackaging("swc"); + themeArtifact.addDefaultBinaryArtifact(targetSwcFile); + + // In this case we don't want the resources to be copied. + super.writeArtifact(themeArtifact); + } + } + } + } + } + + protected void generateMxFteThemeArtifact(File themeCssFile) throws ConverterException { + final String themeName = "mxfte"; + + // Generate and Copy the SWC. + final File targetSwcFile = generateThemeSwc(themeCssFile); + + if(targetSwcFile != null) { + // Generate the pom file. + final MavenArtifact themeArtifact = new MavenArtifact(); + themeArtifact.setGroupId("org.apache.flex.framework.themes"); + themeArtifact.setArtifactId(themeName); + themeArtifact.setVersion(flexSdkVersion); + themeArtifact.setPackaging("swc"); + themeArtifact.addDefaultBinaryArtifact(targetSwcFile); + + // In this case we don't want the resources to be copied. + super.writeArtifact(themeArtifact); + } + } + + protected File generateThemeSwc(File themeDirectory) throws ConverterException { + final File fdkLibDir = new File(rootSourceDirectory, "lib"); + + List<String> processCmd = new ArrayList<String>(10); + + if(fdkLibDir.exists() && fdkLibDir.isDirectory()) { + try { + final File compcLibrary = new File(fdkLibDir, "compc.jar"); + final File frameworkDir = new File(rootSourceDirectory, "frameworks"); + final String targetPlayer = getTargetPlayer(new File(frameworkDir, "libs/player")); + if(targetPlayer == null) { + System.out.println("Skipping theme compilation due to missing playerglobl.swc"); + return null; + } + + processCmd.add("java"); + processCmd.add("-Xmx384m"); + processCmd.add("-Dsun.io.useCanonCaches=false"); + processCmd.add("-jar"); + processCmd.add(compcLibrary.getCanonicalPath()); + processCmd.add("+flexlib=" + frameworkDir.getCanonicalPath()); + processCmd.add("-target-player=" + targetPlayer); + + if (themeDirectory.isDirectory()) { + // Add all the content files. + final File contents[] = themeDirectory.listFiles(new FileFilter() { + public boolean accept(File pathname) { + return !(pathname.isDirectory() && "src".equals(pathname.getName())) && + !"preview.jpg".equals(pathname.getName()) && !pathname.getName().endsWith(".fla"); + } + }); + if (contents.length == 0) { + return null; + } + + for (final File resource : contents) { + processCmd.add("-include-file"); + processCmd.add(resource.getName()); + processCmd.add(resource.getCanonicalPath()); + } + } else { + processCmd.add("-include-file"); + processCmd.add(themeDirectory.getName()); + processCmd.add(themeDirectory.getCanonicalPath()); + } + + // Create a temp file. + final File targetFile = File.createTempFile(themeDirectory.getName(), "swc"); + + // Define the output file. + processCmd.add("-o"); + processCmd.add(targetFile.getCanonicalPath()); + + final File targetDirectory = targetFile.getParentFile(); + if (!targetDirectory.exists()) { + if (!targetDirectory.mkdirs()) { + throw new RuntimeException("Could not create directory: " + targetDirectory.getCanonicalPath()); + } + } + + // Execute the command. + try { + System.out.println("Generating theme '" + themeDirectory.getName() + "'"); + + //final Process child = Runtime.getRuntime().exec(cmd.toString(), envps); + ProcessBuilder processBuilder = new ProcessBuilder(processCmd); + processBuilder.environment().put("PLAYERGLOBAL_HOME", + new File(new File(frameworkDir, "libs"), "player").getCanonicalPath()); + int exitValue = exec(processBuilder.start()); + if (exitValue != 0) { + System.out.println("Couldn't create theme swc"); + System.out.println("----------------------------------------------------------------"); + System.out.println("Env: '" + processBuilder.environment().get("PLAYERGLOBAL_HOME") + "'"); + System.out.println(processBuilder.command()); + System.out.println("----------------------------------------------------------------"); + } + } catch (Exception e) { + e.printStackTrace(); + } + + // Return a reference on the theme swc. + return targetFile; + } catch(IOException e) { + throw new ConverterException("Error generating theme swc.", e); + } + } + return null; + } + + protected int exec(Process p) throws InterruptedException, IOException { + String line; + BufferedReader bri = new BufferedReader(new InputStreamReader(p.getInputStream())); + BufferedReader bre = new BufferedReader(new InputStreamReader(p.getErrorStream())); + while ((line = bri.readLine()) != null) { + System.out.println(line); + } + while ((line = bre.readLine()) != null) { + System.out.println(line); + } + int result = p.waitFor(); + bri.close(); + bre.close(); + System.out.println("Done."); + return result; + } + + private void addFileToZip(ZipOutputStream zipOutputStream, File inputFile, File rootDirectory) + throws ConverterException { + if (inputFile == null) { + return; + } + + // If this is a directory, add all it's children. + if (inputFile.isDirectory()) { + final File directoryContent[] = inputFile.listFiles(); + if (directoryContent != null) { + for (final File file : directoryContent) { + addFileToZip(zipOutputStream, file, rootDirectory); + } + } + } + // If this is a file, add it to the zips output. + else { + byte[] buf = new byte[1024]; + try { + final FileInputStream in = new FileInputStream(inputFile); + final String zipPath = inputFile.getAbsolutePath().substring( + rootDirectory.getAbsolutePath().length() + 1).replace("\\", "/"); + zipOutputStream.putNextEntry(new ZipEntry(zipPath)); + int len; + while ((len = in.read(buf)) > 0) { + zipOutputStream.write(buf, 0, len); + } + zipOutputStream.closeEntry(); + in.close(); + } catch(IOException e) { + throw new ConverterException("Error adding files to zip.", e); + } + } + } + + /** + * Get the version of an Flex SDK from the content of the SDK directory. + * + * @return version string for the current Flex SDK + */ + protected String getFlexVersion(File rootDirectory) throws ConverterException { + final File sdkDescriptor = new File(rootDirectory, "flex-sdk-description.xml"); + + // If the descriptor is not present, return null as this FDK directory doesn't + // seem to contain a Flex SDK. + if(!sdkDescriptor.exists()) { + return null; + } + + final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + try { + // Parse the document + final DocumentBuilder db = dbf.newDocumentBuilder(); + final Document dom = db.parse(sdkDescriptor); + + // Get name, version and build nodes + final Element root = dom.getDocumentElement(); + final String version = root.getElementsByTagName("version").item(0).getTextContent(); + final String build = root.getElementsByTagName("build").item(0).getTextContent(); + + // In general the version consists of the content of the version element with an appended build-number. + return (build.equals("0")) ? version + "-SNAPSHOT" : version; + } catch (ParserConfigurationException pce) { + throw new RuntimeException(pce); + } catch (SAXException se) { + throw new RuntimeException(se); + } catch (IOException ioe) { + throw new RuntimeException(ioe); + } + } + + /** + * Get the version of an Flex SDK from the content of the SDK directory. + * + * @return version string for the current Flex SDK + */ + protected String getFlexBuild(File rootDirectory) throws ConverterException { + final File sdkDescriptor = new File(rootDirectory, "flex-sdk-description.xml"); + + // If the descriptor is not present, return null as this FDK directory doesn't + // seem to contain a Flex SDK. + if(!sdkDescriptor.exists()) { + return null; + } + + final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + try { + // Parse the document + final DocumentBuilder db = dbf.newDocumentBuilder(); + final Document dom = db.parse(sdkDescriptor); + + // Get name, version and build nodes + final Element root = dom.getDocumentElement(); + return root.getElementsByTagName("build").item(0).getTextContent(); + } catch (ParserConfigurationException pce) { + throw new RuntimeException(pce); + } catch (SAXException se) { + throw new RuntimeException(se); + } catch (IOException ioe) { + throw new RuntimeException(ioe); + } + } + + protected File getRsl(String artifactId) { + final FlexRslFilter filter = new FlexRslFilter(artifactId, flexSdkVersion, flexBuild); + final File rslDirectory = new File(rootSourceDirectory, "frameworks" + File.separator + "rsls"); + final File[] rsls = rslDirectory.listFiles(filter); + if ((rsls != null) && (rsls.length == 1)) { + return rsls[0]; + } + return null; + } + + protected File getSignedRsl(String artifactId) { + final FlexSignedRslFilter filter = new FlexSignedRslFilter(artifactId, flexSdkVersion); + final File rslDirectory = new File(rootSourceDirectory, "frameworks" + File.separator + "rsls"); + final File[] swzs = rslDirectory.listFiles(filter); + if ((swzs != null) && (swzs.length == 1)) { + return swzs[0]; + } + return null; + } + + protected Map<String, File> getResourceBundles(String artifactId) { + final Map<String, File> bundles = new HashMap<String, File>(); + final FlexResourceBundleFilter filter = new FlexResourceBundleFilter(artifactId); + final File[] languages = new File(rootSourceDirectory, "frameworks" + File.separator + "locale").listFiles(); + if(languages != null) { + for (final File language : languages) { + final File[] resources = language.listFiles(filter); + if ((resources != null) && (resources.length == 1)) { + bundles.put(language.getName(), resources[0]); + } + } + } + return bundles; + } + + protected String getTargetPlayer(File playerDir) { + if(playerDir.exists() && playerDir.isDirectory()) { + File[] files = playerDir.listFiles(); + if((files != null) && files.length > 0) { + return files[0].getName(); + } + } + return null; + } + + public static class FlexCompilerFilter implements FilenameFilter { + private AirConverter.AirCompilerFilter airFilter = new AirConverter.AirCompilerFilter(); + + public boolean accept(File dir, String name) { + return name.endsWith(".jar") && !airFilter.accept(dir, name) && + // Some old AIR SDKs contained two android libs in the main lib directory, + // we have to manually exclude them. + !name.equals("smali.jar") && !name.equals("baksmali.jar"); + } + } + + public static class FlexFrameworkFilter implements FilenameFilter { + private AirConverter.AirFrameworkFilter airFilter = new AirConverter.AirFrameworkFilter(); + private FlashConverter.FlashFrameworkFilter flashFilter = new FlashConverter.FlashFrameworkFilter(); + + public boolean accept(File dir, String name) { + return name.endsWith(".swc") && !airFilter.accept(dir, name) && !flashFilter.accept(dir, name); + } + } + + public static class FlexRslFilter implements FilenameFilter { + private String fileName; + + public FlexRslFilter(String artifactName, String artifactVersion, String build) { + this.fileName = artifactName + "_" + artifactVersion + "." + build + ".swf"; + } + + public boolean accept(File dir, String name) { + return name.equals(fileName); + } + } + + public static class FlexSignedRslFilter implements FilenameFilter { + private String fileName; + + public FlexSignedRslFilter(String artifactName, String artifactVersion) { + this.fileName = artifactName + "_" + artifactVersion + ".swz"; + } + + public boolean accept(File dir, String name) { + return name.equals(fileName); + } + } + + public static class FlexResourceBundleFilter implements FilenameFilter { + private String fileName; + + public FlexResourceBundleFilter(String artifactName) { + this.fileName = artifactName + "_rb.swc"; + } + + public boolean accept(File dir, String name) { + return name.equals(fileName); + } + } + + public static void main(String[] args) throws Exception { + FlexConverter converter = new FlexConverter(new File(args[0]), new File(args[1])); + converter.convert(); + } + +}
