1 /* 2 * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package com.apple.internal.jobjc.generator.model; 26 27 import java.io.File; 28 import java.io.IOException; 29 import java.util.ArrayList; 30 import java.util.Collection; 31 import java.util.HashSet; 32 import java.util.List; 33 import java.util.Map; 34 import java.util.Set; 35 36 import javax.xml.xpath.XPath; 37 import javax.xml.xpath.XPathConstants; 38 import javax.xml.xpath.XPathExpressionException; 39 import javax.xml.xpath.XPathFactory; 40 41 import org.w3c.dom.Node; 42 import org.xml.sax.InputSource; 43 44 import com.apple.internal.jobjc.generator.ClassGenerator; 45 import com.apple.internal.jobjc.generator.Utils; 46 import com.apple.internal.jobjc.generator.classes.FrameworkClassFile; 47 import com.apple.internal.jobjc.generator.classes.OutputFile; 48 import com.apple.internal.jobjc.generator.utils.Fp; 49 import com.apple.internal.jobjc.generator.utils.Fp.Map1; 50 import com.apple.jobjc.MacOSXFramework; 51 import com.apple.jobjc.UnsafeRuntimeAccess; 52 53 public class Framework extends Element<Element<?>> implements OutputFileGenerator { 54 public final String path; 55 public final String pkg; 56 public final List<File> binaries; 57 public MacOSXFramework nativeFramework; 58 load()59 public MacOSXFramework load(){ 60 if(nativeFramework == null){ 61 String[] bins = new String[binaries.size()]; 62 for(int i = 0; i < binaries.size(); ++i) 63 bins[i] = Utils.getCanonicalPath(binaries.get(i)); 64 nativeFramework = UnsafeRuntimeAccess.getFramework(bins); 65 } 66 return nativeFramework; 67 } 68 getMainFrameworkBinary()69 public File getMainFrameworkBinary(){ return binaries.get(0); } 70 71 final Node rootNode; 72 73 public Set<Clazz> classes; 74 public List<Struct> structs; 75 public List<CFType> cfTypes; 76 public List<Opaque> opaques; 77 public List<Constant> constants; 78 public List<StringConstant> stringConstants; 79 public List<NativeEnum> enums; 80 public List<Function> functions; 81 public List<FunctionAlias> functionAliases; 82 public List<InformalProtocol> informalProtocols; 83 public List<Protocol> protocols; 84 public List<Category> categories; 85 public List<FrameworkDependency> dependencies; 86 87 public static class FrameworkDependency extends Element<Framework>{ 88 final String path; 89 public Framework object = null; 90 FrameworkDependency(final Node node, final Framework parent)91 public FrameworkDependency(final Node node, final Framework parent) { 92 super(getAttr(node, "path").replaceFirst("^.*/([^/]+)\\.framework$", "$1"), parent); 93 this.path = getAttr(node, "path"); 94 } 95 } 96 97 public static final XPath XPATH = XPathFactory.newInstance().newXPath(); Framework(final String name, final File bsFile)98 public Framework(final String name, final File bsFile) { 99 super(name, null); 100 try { 101 final File pathf = bsFile.getCanonicalFile().getParentFile().getParentFile().getParentFile(); 102 path = pathf.getParentFile().getParentFile().getCanonicalPath(); 103 } catch (IOException x) { 104 throw new RuntimeException(x); 105 } 106 binaries = findBinaries(path, name); 107 108 pkg = ClassGenerator.JOBJC_PACKAGE + "." + name.toLowerCase(); 109 try { 110 rootNode = (Node)XPATH.evaluate("signatures", new InputSource(bsFile.getAbsolutePath()), XPathConstants.NODE); 111 } catch (final XPathExpressionException e) { throw new RuntimeException(e); } 112 protocols = new ArrayList<Protocol>(); 113 categories = new ArrayList<Category>(); 114 } 115 findBinaries(final String rootPath, final String name)116 private static List<File> findBinaries(final String rootPath, final String name){ 117 List<File> bins = new ArrayList<File>(2); 118 119 File mainBin = new File(rootPath, name); 120 if(mainBin.exists()) bins.add(mainBin); 121 122 File bsBin = new File(rootPath, "Resources/BridgeSupport/" + name + ".dylib"); 123 if(bsBin.exists()) bins.add(bsBin); 124 125 return bins; 126 } 127 parseDependencies(final Collection<Framework> frameworks)128 public void parseDependencies(final Collection<Framework> frameworks) { 129 // Parse 130 dependencies = getNodesFor(rootNode, "depends_on", FrameworkDependency.class, this); 131 // Resolve 132 for(final FrameworkDependency dep : dependencies) 133 dep.object = Fp.find(new Map1<Framework,Boolean>(){ 134 public Boolean apply(Framework f) { 135 return f.path.equals(dep.path); 136 }}, frameworks); 137 } 138 parseStructs()139 public void parseStructs() { 140 structs = getNodesFor(rootNode, "struct", Struct.class, this); 141 142 // HACK BS bug #6100313 143 if(Utils.isSnowLeopard && name.equals("IOBluetooth")) 144 structs.remove(getStructByName("BluetoothHCIRequestNotificationInfo")); 145 146 // GLIFunctionDispatch is frequently out of sync in BS / system 147 if(name.equals("OpenGL")) 148 structs.remove(getStructByName("GLIFunctionDispatch")); 149 } 150 parseCFTypes()151 public void parseCFTypes() { 152 cfTypes = getNodesFor(rootNode, "cftype", CFType.class, this); 153 } 154 parseOpaques()155 public void parseOpaques() { 156 opaques = getNodesFor(rootNode, "opaque", Opaque.class, this); 157 } 158 parseConstants()159 public void parseConstants() { 160 constants = getNodesFor(rootNode, "constant", Constant.class, this); 161 stringConstants = getNodesFor(rootNode, "string_constant", StringConstant.class, this); 162 enums = getNodesFor(rootNode, "enum", NativeEnum.class, this); 163 } 164 parseFunctions()165 public void parseFunctions() { 166 functions = getNodesFor(rootNode, "function", Function.class, this); 167 functionAliases = getNodesFor(rootNode, "function_alias", FunctionAlias.class, this); 168 } 169 parseClasses()170 public void parseClasses() { 171 classes = new HashSet<Clazz>(getNodesFor(rootNode, "class", Clazz.class, this)); 172 classes = Fp.filterSet(new Map1<Clazz,Boolean>(){ 173 public Boolean apply(Clazz a) { 174 if(a.doesActuallyExist()) 175 return true; 176 else{ 177 System.out.println("Could not find class " + name + ":" + a.name + " in runtime. Discarding."); 178 return false; 179 } 180 }}, classes); 181 informalProtocols = getNodesFor(rootNode, "informal_protocol", InformalProtocol.class, this); 182 } 183 resolveSuperClasses(final Map<String, Clazz> allClasses)184 public void resolveSuperClasses(final Map<String, Clazz> allClasses) throws Throwable { 185 load(); 186 for (final Clazz clazz : classes) 187 clazz.resolveSuperClass(nativeFramework, allClasses); 188 } 189 generateClasses(final List<OutputFile> generatedClassFiles)190 public void generateClasses(final List<OutputFile> generatedClassFiles) { 191 generatedClassFiles.add(new FrameworkClassFile(this)); 192 193 final List<List<OutputFileGenerator>> generatorLists = 194 Utils.list(new ArrayList<Clazz>(classes), structs, cfTypes, opaques, categories); 195 for (final List<OutputFileGenerator> generators : generatorLists) { 196 for (final OutputFileGenerator generator : generators) 197 generator.generateClasses(generatedClassFiles); 198 } 199 } 200 toString()201 @Override public String toString() { return reflectOnMySelf(); } 202 getStructByName(final String stname)203 public Struct getStructByName(final String stname) { 204 return Fp.find(new Fp.Map1<Struct,Boolean>(){ 205 public Boolean apply(Struct a) { 206 return stname.equals(a.name); 207 }}, structs); 208 } 209 } 210