blob: ae82b250a54144f81ab2de192cb1940b06f9ae10 [file] [log] [blame]
/*
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package mustella;
import java.io.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import org.w3c.dom.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.StreamResult;
import utils.*;
/**
Writes application descriptor files for AIR
*/
public class ApolloAdjuster {
static String swffile = null;
static String xmlfile = null;
static String xmlfile2 = null;
static String delete_file = null;
static String deviceName = "";
/// the template file.
static String template_location = "/templates/air/descriptor-template.xml";
static String model_file = System.getProperty ("apollo_location") + template_location;
static String xmlnsVal = "http://ns.adobe.com/air/application/1.0";
static {
try {
if (System.getProperty ("air_xmlns") != null)
xmlnsVal = System.getProperty ("air_xmlns");
} catch (Exception e) {
/// leave it
}
try {
deviceName = System.getProperty( "device_name" );
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* use the template that's part of the distribution to create the
* application descriptor file.
* See code comments for details.
*/
public static String xmlTransformFromTemplate ( boolean includeSwfParent ) throws Exception {
DocumentBuilder docb = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = docb.parse (new File(model_file));
NodeList nl = null;
String justSwf = getSwfName ( swffile, false );
String appid = justSwf.substring( 0, justSwf.indexOf( ".swf" ) ).replace( "_", "" );
String content = getSwfName ( swffile, includeSwfParent );
/// modify the pieces we need to: content:
nl = doc.getElementsByTagName("content");
if ( nl.item(0).getFirstChild() == null) {
Text t = doc.createTextNode (content);
nl.item(0).appendChild(t);
} else
nl.item(0).getFirstChild().setNodeValue(content);
/// modify the pieces we need to: filename
// Note: The adt tool doesn't like filename to be exactly the same as the name of the swf.
nl = doc.getElementsByTagName("filename");
if ( nl.item(0).getFirstChild() == null) {
Text ft = doc.createTextNode (appid);
nl.item(0).appendChild (ft);
} else {
nl.item(0).getFirstChild().setNodeValue(appid);
}
/// modify the pieces we need to: id
nl = doc.getElementsByTagName("id");
if ( nl.item(0).getFirstChild() == null) {
Text it = doc.createTextNode (appid);
nl.item(0).appendChild (it);
} else
nl.item(0).getFirstChild().setNodeValue(appid);
nl = doc.getElementsByTagName("versionNumber");
if ( nl != null && nl.item(0) != null ) {
if (nl.item(0).getFirstChild() == null) {
Text vit = doc.createTextNode ("1.0.0");
nl.item(0).appendChild (vit);
} else {
nl.item(0).getFirstChild().setNodeValue("1.0.0");
}
}
/// modify the pieces we need to: android
if( deviceName != null ){
if( MobileUtil.getOSForDevice( deviceName ).compareToIgnoreCase( MobileUtil.ANDROID_OS ) == 0 ){
nl = doc.getElementsByTagName("application");
Element el = doc.createElement("android");
Node el2 = el.appendChild( doc.createElement("manifestAdditions") );
el2.appendChild( doc.createCDATASection("\n\t<manifest>" +
"\n\t\t<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" />" +
"\n\t\t<uses-permission android:name=\"android.permission.INTERNET\" />" +
"\n\t\t<uses-permission android:name=\"android.permission.WAKE_LOCK\" />" +
"\n\t\t<uses-permission android:name=\"android.permission.DISABLE_KEYGUARD\" />" +
"\n\t\t<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\" />" +
"\n\t\t<uses-permission android:name=\"android.permission.READ_PHONE_STATE\" />" +
"\n\t\t<uses-permission android:name=\"android.permission.CAMERA\" />" +
"\n\t\t<uses-permission android:name=\"android.permission.RECORD_AUDIO\" />" +
"\n\t</manifest>\n"));
nl.item(0).appendChild(el);
// For namespace 3.1 and after, use 16 bit color for Android due to performance issues.
Element colorDepth = doc.createElement("colorDepth");
Text colorDepthVal = doc.createTextNode ("16bit");
colorDepth.appendChild(colorDepthVal);
el.appendChild(colorDepth);
// Set the softKeyboardBehavior in initialWindow. This is only supported in Android right now, and
// this code can just be moved if it ends up being supported for other devices.
Element softKeyboardBehavior = doc.createElement("softKeyboardBehavior");
Text softKeyboardBehaviorVal = doc.createTextNode ("none");
softKeyboardBehavior.appendChild(softKeyboardBehaviorVal);
nl = doc.getElementsByTagName ("initialWindow");
nl.item(0).appendChild (softKeyboardBehavior);
}
}
/// modify the pieces we need to: iOS
if( deviceName != null ){
if( MobileUtil.getOSForDevice( deviceName ).compareToIgnoreCase( MobileUtil.IOS ) == 0 ){
// Add fullScreen, autoOrients, aspectRatio, and renderMode to initialWindow. I'm not sure which of these
// are absolutely needed, but I do know that the file which works contains these items in addition to the above.
Element fullScreen = doc.createElement("fullScreen");
Text fullScreenVal = doc.createTextNode ("true");
fullScreen.appendChild (fullScreenVal);
Element autoOrients = doc.createElement("autoOrients");
Text autoOrientsVal = doc.createTextNode ("true");
autoOrients.appendChild (autoOrientsVal);
Element aspectRatio = doc.createElement("aspectRatio");
Text aspectRatioVal = doc.createTextNode ("portrait");
aspectRatio.appendChild (aspectRatioVal);
Element renderMode = doc.createElement("renderMode");
Text renderModeVal = doc.createTextNode ("cpu");
renderMode.appendChild (renderModeVal);
nl = doc.getElementsByTagName ("initialWindow");
nl.item(0).appendChild(fullScreen);
nl.item(0).appendChild(autoOrients);
nl.item(0).appendChild(aspectRatio);
nl.item(0).appendChild(renderMode);
// Run iOS tests in high resolution mode. Add these to the application node.
nl = doc.getElementsByTagName("application");
Element el = doc.createElement("iPhone");
Node el2 = el.appendChild( doc.createElement("InfoAdditions") );
el2.appendChild( doc.createCDATASection("\n\t<key>UIDeviceFamily</key>" +
"\n\t\t<array>" +
"\n\t\t\t<string>1</string>" +
"\n\t\t\t<string>2</string>" +
"\n\t\t</array>" +
"\n\t\t<key>UIStatusBarStyle</key>" +
"\n\t\t<string>UIStatusBarStyleBlackOpaque</string>" +
"\n\t\t<key>UIRequiresPersistentWiFi</key>" +
"\n\t\t<string>YES</string>"));
nl.item(0).appendChild(el);
nl = doc.getElementsByTagName("iPhone");
Element reqDisplayRes = doc.createElement("requestedDisplayResolution");
Text reqDisplayResVal = doc.createTextNode ("high");
reqDisplayRes.appendChild(reqDisplayResVal);
nl.item(0).appendChild(reqDisplayRes);
}
}
// modify the pieces we need to: name. Be sure it's no more than 25 characters (QNX restriction).
if( deviceName != null ){
if( MobileUtil.getOSForDevice( deviceName ).compareToIgnoreCase( MobileUtil.QNX ) == 0 ){
String appName = appid;
if( appName.length() > 25 ){
appName = appName.substring( 0, 25 );
}
nl = doc.getElementsByTagName( "name" );
if ( nl.item(0).getFirstChild() == null ) {
Text nameNode = doc.createTextNode ( appName );
nl.item(0).appendChild ( nameNode );
} else
nl.item(0).getFirstChild().setNodeValue( appName );
}
}
/// modify the pieces we need to: systemChrome (we like 'none')
/// this is commented out in the template, so we just add it
Element sysChrome = doc.createElement("systemChrome");
Text chrome = doc.createTextNode ("none");
sysChrome.appendChild (chrome);
/// modify the pieces we need to: transparent (we like 'true')
/// this is commented out in the template, so we just add it
Element trans = doc.createElement("transparent");
Text transt = doc.createTextNode ("true");
trans.appendChild (transt);
/// modify the pieces we need to: visible (we like 'true')
/// this is commented out in the template, so we just add it
Element viz = doc.createElement("visible");
Text transv = doc.createTextNode ("true");
viz.appendChild (transv);
/// put them in the InitialWindow section
nl = doc.getElementsByTagName ("initialWindow");
nl.item(0).appendChild(sysChrome);
nl.item(0).appendChild(trans);
nl.item(0).appendChild(viz);
/// output the result
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
//initialize StreamResult with File object to save to file
StreamResult result = new StreamResult(new StringWriter());
DOMSource source = new DOMSource(doc);
transformer.transform(source, result);
String xmlString = result.getWriter().toString();
return xmlString;
}
public static String xmlWriter (String file) {
return xmlWriter (file, true);
}
public static String xmlWriter (String file, boolean deleteIt) {
return xmlWriter (file, deleteIt, false);
}
public static String xmlWriter (String file, boolean deleteIt, boolean includeSwfParent) {
System.out.println ("apollo adj with : " + file);
if (file.indexOf (".swf") != -1) {
System.out.println ("apollo adj thinks it's a swf");
swffile = file;
// builder's generated name
xmlfile = file.substring (0, file.indexOf (".swf")) + ".xml";
if (deleteIt)
delete_file = file.substring (0, file.indexOf (".swf")) + ".delete";
else
delete_file = null;
} else if (file.indexOf (".xml") != -1) {
xmlfile = file;
swffile = file.substring (0, file.indexOf (".xml")) + ".swf";
if (deleteIt)
delete_file = file.substring (0, file.indexOf (".xml")) + ".delete";
else
delete_file = null;
}
/// check if it exists.
if (new File(xmlfile).exists() && (delete_file == null || !new File(delete_file).exists())) {
System.out.println ("not writing Apollo file");
return xmlfile;
} else {
System.out.println ("writing Apollo file!");
createFile( includeSwfParent );
}
return xmlfile;
}
public static boolean didWrite () {
try {
return new File(delete_file).exists();
} catch (Exception e) {
return false;
}
}
public static void delete () {
System.out.println ("removing the xml app file");
new File(delete_file).delete();
new File(xmlfile).delete();
}
public static String getSwfName (String file, boolean includeSwfParent) {
String ret = null;
String left = null;
String right = null;
if (includeSwfParent){
right = file.substring( file.lastIndexOf( File.separator ) + 1 ); // ButtonMain.swf
right = "/" + right; // /ButtonMain.swf, must be a /, cannot be a \.
left = file.substring( 0, file.lastIndexOf( File.separator ) ); // blah/blah/Button/swfs
left = left.substring( left.lastIndexOf( File.separator ) +1 ); // swfs
ret = left + right; // swfs/ButtonMain.swf
}else{
if (file.indexOf("/") != -1) {
ret = file.substring (file.lastIndexOf("/")+1);
} else if (file.indexOf(File.separator) != -1) {
ret = file.substring (file.lastIndexOf(File.separator)+1);
} else {
ret = file;
}
}
return ret;
}
public static void createFile ( boolean includeSwfParent ) {
System.out.println ("full swf is " + swffile);
FileOutputStream bos = null;
FileOutputStream bos2 = null;
try {
/// get the contents we'll write:
String xmlString = xmlTransformFromTemplate( includeSwfParent );
/// write a marker to delete the file we'll write
if (delete_file != null) {
bos2 = new FileOutputStream (delete_file);
bos2.write ("0".getBytes(), 0, 1);
bos2.flush();
bos2.close();
}
/// write the xml file
bos = new FileOutputStream (xmlfile);
bos.write (xmlString.getBytes(), 0, xmlString.length());
bos.flush();
bos.close();
} catch (Exception e) {
e.printStackTrace();
try {
bos.close();
bos2.close();
} catch (Exception e2) {
}
}
}
public static void main (String [] args) throws Exception {
xmlWriter (args[0]);
}
}