/** * Creates the default, nameless, DecimalFormat object in AbstractTranslet's format_symbols * hashtable. This should be called for every stylesheet, and the entry may be overridden by later * nameless xsl:decimal-format instructions. */ public static void translateDefaultDFS(ClassGenerator classGen, MethodGenerator methodGen) { ConstantPoolGen cpg = classGen.getConstantPool(); InstructionList il = methodGen.getInstructionList(); final int init = cpg.addMethodref(DFS_CLASS, "<init>", "(" + LOCALE_SIG + ")V"); // Push the format name, which is empty, on the stack // for call to addDecimalFormat() il.append(classGen.loadTranslet()); il.append(new PUSH(cpg, EMPTYSTRING)); // Manufacture a DecimalFormatSymbols on the stack for // call to addDecimalFormat(). Use the US Locale as the // default, as most of its settings are equivalent to // the default settings required of xsl:decimal-format - // except for the NaN and infinity attributes. il.append(new NEW(cpg.addClass(DFS_CLASS))); il.append(DUP); il.append(new GETSTATIC(cpg.addFieldref(LOCALE_CLASS, "US", LOCALE_SIG))); il.append(new INVOKESPECIAL(init)); int nan = cpg.addMethodref(DFS_CLASS, "setNaN", "(Ljava/lang/String;)V"); il.append(DUP); il.append(new PUSH(cpg, "NaN")); il.append(new INVOKEVIRTUAL(nan)); int inf = cpg.addMethodref(DFS_CLASS, "setInfinity", "(Ljava/lang/String;)V"); il.append(DUP); il.append(new PUSH(cpg, "Infinity")); il.append(new INVOKEVIRTUAL(inf)); final int put = cpg.addMethodref(TRANSLET_CLASS, "addDecimalFormat", "(" + STRING_SIG + DFS_SIG + ")V"); il.append(new INVOKEVIRTUAL(put)); }
public void translate(ClassGenerator classGen, MethodGenerator methodGen) { final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = methodGen.getInstructionList(); if (!_isLiteral) { // if the ncname is an AVT, then the ncname has to be checked at runtime if it is a valid // ncname LocalVariableGen nameValue = methodGen.addLocalVariable2("nameValue", Util.getJCRefType(STRING_SIG), null); // store the name into a variable first so _name.translate only needs to be called once _name.translate(classGen, methodGen); nameValue.setStart(il.append(new ASTORE(nameValue.getIndex()))); il.append(new ALOAD(nameValue.getIndex())); // call checkNCName if the name is an AVT final int check = cpg.addMethodref(BASIS_LIBRARY_CLASS, "checkNCName", "(" + STRING_SIG + ")V"); il.append(new INVOKESTATIC(check)); // Save the current handler base on the stack il.append(methodGen.loadHandler()); il.append(DUP); // first arg to "attributes" call // load name value again nameValue.setEnd(il.append(new ALOAD(nameValue.getIndex()))); } else { // Save the current handler base on the stack il.append(methodGen.loadHandler()); il.append(DUP); // first arg to "attributes" call // Push attribute name _name.translate(classGen, methodGen); // 2nd arg } il.append(classGen.loadTranslet()); il.append( new GETFIELD( cpg.addFieldref(TRANSLET_CLASS, "stringValueHandler", STRING_VALUE_HANDLER_SIG))); il.append(DUP); il.append(methodGen.storeHandler()); // translate contents with substituted handler translateContents(classGen, methodGen); // get String out of the handler il.append( new INVOKEVIRTUAL( cpg.addMethodref(STRING_VALUE_HANDLER, "getValueOfPI", "()" + STRING_SIG))); // call "processingInstruction" final int processingInstruction = cpg.addInterfaceMethodref( TRANSLET_OUTPUT_INTERFACE, "processingInstruction", "(" + STRING_SIG + STRING_SIG + ")V"); il.append(new INVOKEINTERFACE(processingInstruction, 3)); // Restore old handler base from stack il.append(methodGen.storeHandler()); }
/** Compile the translet's constructor */ private void compileConstructor(ClassGenerator classGen, Output output) { final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = new InstructionList(); final MethodGenerator constructor = new MethodGenerator( ACC_PUBLIC, com.sun.org.apache.bcel.internal.generic.Type.VOID, null, null, "<init>", _className, il, cpg); // Call the constructor in the AbstractTranslet superclass il.append(classGen.loadTranslet()); il.append(new INVOKESPECIAL(cpg.addMethodref(TRANSLET_CLASS, "<init>", "()V"))); constructor.markChunkStart(); il.append(classGen.loadTranslet()); il.append( new GETSTATIC(cpg.addFieldref(_className, STATIC_NAMES_ARRAY_FIELD, NAMES_INDEX_SIG))); il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS, NAMES_INDEX, NAMES_INDEX_SIG))); il.append(classGen.loadTranslet()); il.append(new GETSTATIC(cpg.addFieldref(_className, STATIC_URIS_ARRAY_FIELD, URIS_INDEX_SIG))); il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS, URIS_INDEX, URIS_INDEX_SIG))); constructor.markChunkEnd(); constructor.markChunkStart(); il.append(classGen.loadTranslet()); il.append( new GETSTATIC(cpg.addFieldref(_className, STATIC_TYPES_ARRAY_FIELD, TYPES_INDEX_SIG))); il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS, TYPES_INDEX, TYPES_INDEX_SIG))); constructor.markChunkEnd(); constructor.markChunkStart(); il.append(classGen.loadTranslet()); il.append( new GETSTATIC( cpg.addFieldref(_className, STATIC_NAMESPACE_ARRAY_FIELD, NAMESPACE_INDEX_SIG))); il.append(new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS, NAMESPACE_INDEX, NAMESPACE_INDEX_SIG))); constructor.markChunkEnd(); constructor.markChunkStart(); il.append(classGen.loadTranslet()); il.append(new PUSH(cpg, AbstractTranslet.CURRENT_TRANSLET_VERSION)); il.append( new PUTFIELD( cpg.addFieldref(TRANSLET_CLASS, TRANSLET_VERSION_INDEX, TRANSLET_VERSION_INDEX_SIG))); constructor.markChunkEnd(); if (_hasIdCall) { constructor.markChunkStart(); il.append(classGen.loadTranslet()); il.append(new PUSH(cpg, Boolean.TRUE)); il.append( new PUTFIELD(cpg.addFieldref(TRANSLET_CLASS, HASIDCALL_INDEX, HASIDCALL_INDEX_SIG))); constructor.markChunkEnd(); } // Compile in code to set the output configuration from <xsl:output> if (output != null) { // Set all the output settings files in the translet constructor.markChunkStart(); output.translate(classGen, constructor); constructor.markChunkEnd(); } // Compile default decimal formatting symbols. // This is an implicit, nameless xsl:decimal-format top-level element. if (_numberFormattingUsed) { constructor.markChunkStart(); DecimalFormatting.translateDefaultDFS(classGen, constructor); constructor.markChunkEnd(); } il.append(RETURN); classGen.addMethod(constructor); }
/** * Compile the namesArray, urisArray and typesArray into the static initializer. They are * read-only from the translet. All translet instances can share a single copy of this informtion. */ private void compileStaticInitializer(ClassGenerator classGen) { final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = new InstructionList(); final MethodGenerator staticConst = new MethodGenerator( ACC_PUBLIC | ACC_STATIC, com.sun.org.apache.bcel.internal.generic.Type.VOID, null, null, "<clinit>", _className, il, cpg); addStaticField(classGen, "[" + STRING_SIG, STATIC_NAMES_ARRAY_FIELD); addStaticField(classGen, "[" + STRING_SIG, STATIC_URIS_ARRAY_FIELD); addStaticField(classGen, "[I", STATIC_TYPES_ARRAY_FIELD); addStaticField(classGen, "[" + STRING_SIG, STATIC_NAMESPACE_ARRAY_FIELD); // Create fields of type char[] that will contain literal text from // the stylesheet. final int charDataFieldCount = getXSLTC().getCharacterDataCount(); for (int i = 0; i < charDataFieldCount; i++) { addStaticField(classGen, STATIC_CHAR_DATA_FIELD_SIG, STATIC_CHAR_DATA_FIELD + i); } // Put the names array into the translet - used for dom/translet mapping final Vector namesIndex = getXSLTC().getNamesIndex(); int size = namesIndex.size(); String[] namesArray = new String[size]; String[] urisArray = new String[size]; int[] typesArray = new int[size]; int index; for (int i = 0; i < size; i++) { String encodedName = (String) namesIndex.elementAt(i); if ((index = encodedName.lastIndexOf(':')) > -1) { urisArray[i] = encodedName.substring(0, index); } index = index + 1; if (encodedName.charAt(index) == '@') { typesArray[i] = DTM.ATTRIBUTE_NODE; index++; } else if (encodedName.charAt(index) == '?') { typesArray[i] = DTM.NAMESPACE_NODE; index++; } else { typesArray[i] = DTM.ELEMENT_NODE; } if (index == 0) { namesArray[i] = encodedName; } else { namesArray[i] = encodedName.substring(index); } } staticConst.markChunkStart(); il.append(new PUSH(cpg, size)); il.append(new ANEWARRAY(cpg.addClass(STRING))); int namesArrayRef = cpg.addFieldref(_className, STATIC_NAMES_ARRAY_FIELD, NAMES_INDEX_SIG); il.append(new PUTSTATIC(namesArrayRef)); staticConst.markChunkEnd(); for (int i = 0; i < size; i++) { final String name = namesArray[i]; staticConst.markChunkStart(); il.append(new GETSTATIC(namesArrayRef)); il.append(new PUSH(cpg, i)); il.append(new PUSH(cpg, name)); il.append(AASTORE); staticConst.markChunkEnd(); } staticConst.markChunkStart(); il.append(new PUSH(cpg, size)); il.append(new ANEWARRAY(cpg.addClass(STRING))); int urisArrayRef = cpg.addFieldref(_className, STATIC_URIS_ARRAY_FIELD, URIS_INDEX_SIG); il.append(new PUTSTATIC(urisArrayRef)); staticConst.markChunkEnd(); for (int i = 0; i < size; i++) { final String uri = urisArray[i]; staticConst.markChunkStart(); il.append(new GETSTATIC(urisArrayRef)); il.append(new PUSH(cpg, i)); il.append(new PUSH(cpg, uri)); il.append(AASTORE); staticConst.markChunkEnd(); } staticConst.markChunkStart(); il.append(new PUSH(cpg, size)); il.append(new NEWARRAY(BasicType.INT)); int typesArrayRef = cpg.addFieldref(_className, STATIC_TYPES_ARRAY_FIELD, TYPES_INDEX_SIG); il.append(new PUTSTATIC(typesArrayRef)); staticConst.markChunkEnd(); for (int i = 0; i < size; i++) { final int nodeType = typesArray[i]; staticConst.markChunkStart(); il.append(new GETSTATIC(typesArrayRef)); il.append(new PUSH(cpg, i)); il.append(new PUSH(cpg, nodeType)); il.append(IASTORE); } // Put the namespace names array into the translet final Vector namespaces = getXSLTC().getNamespaceIndex(); staticConst.markChunkStart(); il.append(new PUSH(cpg, namespaces.size())); il.append(new ANEWARRAY(cpg.addClass(STRING))); int namespaceArrayRef = cpg.addFieldref(_className, STATIC_NAMESPACE_ARRAY_FIELD, NAMESPACE_INDEX_SIG); il.append(new PUTSTATIC(namespaceArrayRef)); staticConst.markChunkEnd(); for (int i = 0; i < namespaces.size(); i++) { final String ns = (String) namespaces.elementAt(i); staticConst.markChunkStart(); il.append(new GETSTATIC(namespaceArrayRef)); il.append(new PUSH(cpg, i)); il.append(new PUSH(cpg, ns)); il.append(AASTORE); staticConst.markChunkEnd(); } // Grab all the literal text in the stylesheet and put it in a char[] final int charDataCount = getXSLTC().getCharacterDataCount(); final int toCharArray = cpg.addMethodref(STRING, "toCharArray", "()[C"); for (int i = 0; i < charDataCount; i++) { staticConst.markChunkStart(); il.append(new PUSH(cpg, getXSLTC().getCharacterData(i))); il.append(new INVOKEVIRTUAL(toCharArray)); il.append( new PUTSTATIC( cpg.addFieldref(_className, STATIC_CHAR_DATA_FIELD + i, STATIC_CHAR_DATA_FIELD_SIG))); staticConst.markChunkEnd(); } il.append(RETURN); classGen.addMethod(staticConst); }
/** * Compile transform() into the output class. This method is used to initialize global variables * and global parameters. The current node is set to be the document's root node. */ private void compileTransform(ClassGenerator classGen) { final ConstantPoolGen cpg = classGen.getConstantPool(); /* * Define the the method transform with the following signature: * void transform(DOM, NodeIterator, HandlerBase) */ final com.sun.org.apache.bcel.internal.generic.Type[] argTypes = new com.sun.org.apache.bcel.internal.generic.Type[3]; argTypes[0] = Util.getJCRefType(DOM_INTF_SIG); argTypes[1] = Util.getJCRefType(NODE_ITERATOR_SIG); argTypes[2] = Util.getJCRefType(TRANSLET_OUTPUT_SIG); final String[] argNames = new String[3]; argNames[0] = DOCUMENT_PNAME; argNames[1] = ITERATOR_PNAME; argNames[2] = TRANSLET_OUTPUT_PNAME; final InstructionList il = new InstructionList(); final MethodGenerator transf = new MethodGenerator( ACC_PUBLIC, com.sun.org.apache.bcel.internal.generic.Type.VOID, argTypes, argNames, "transform", _className, il, classGen.getConstantPool()); transf.addException("com.sun.org.apache.xalan.internal.xsltc.TransletException"); // Define and initialize current with the root node final LocalVariableGen current = transf.addLocalVariable( "current", com.sun.org.apache.bcel.internal.generic.Type.INT, null, null); final String applyTemplatesSig = classGen.getApplyTemplatesSig(); final int applyTemplates = cpg.addMethodref(getClassName(), "applyTemplates", applyTemplatesSig); final int domField = cpg.addFieldref(getClassName(), DOM_FIELD, DOM_INTF_SIG); // push translet for PUTFIELD il.append(classGen.loadTranslet()); // prepare appropriate DOM implementation if (isMultiDocument()) { il.append(new NEW(cpg.addClass(MULTI_DOM_CLASS))); il.append(DUP); } il.append(classGen.loadTranslet()); il.append(transf.loadDOM()); il.append( new INVOKEVIRTUAL( cpg.addMethodref( TRANSLET_CLASS, "makeDOMAdapter", "(" + DOM_INTF_SIG + ")" + DOM_ADAPTER_SIG))); // DOMAdapter is on the stack if (isMultiDocument()) { final int init = cpg.addMethodref(MULTI_DOM_CLASS, "<init>", "(" + DOM_INTF_SIG + ")V"); il.append(new INVOKESPECIAL(init)); // MultiDOM is on the stack } // store to _dom variable il.append(new PUTFIELD(domField)); // continue with globals initialization final int gitr = cpg.addInterfaceMethodref(DOM_INTF, "getIterator", "()" + NODE_ITERATOR_SIG); il.append(transf.loadDOM()); il.append(new INVOKEINTERFACE(gitr, 1)); il.append(transf.nextNode()); current.setStart(il.append(new ISTORE(current.getIndex()))); // Transfer the output settings to the output post-processor il.append(classGen.loadTranslet()); il.append(transf.loadHandler()); final int index = cpg.addMethodref(TRANSLET_CLASS, "transferOutputSettings", "(" + OUTPUT_HANDLER_SIG + ")V"); il.append(new INVOKEVIRTUAL(index)); /* * Compile buildKeys() method. Note that this method is not * invoked here as keys for the input document are now created * in topLevel(). However, this method is still needed by the * LoadDocument class. */ final String keySig = compileBuildKeys(classGen); final int keyIdx = cpg.addMethodref(getClassName(), "buildKeys", keySig); // Look for top-level elements that need handling final Enumeration toplevel = elements(); if (_globals.size() > 0 || toplevel.hasMoreElements()) { // Compile method for handling top-level elements final String topLevelSig = compileTopLevel(classGen); // Get a reference to that method final int topLevelIdx = cpg.addMethodref(getClassName(), "topLevel", topLevelSig); // Push all parameters on the stack and call topLevel() il.append(classGen.loadTranslet()); // The 'this' pointer il.append(classGen.loadTranslet()); il.append(new GETFIELD(domField)); // The DOM reference il.append(transf.loadIterator()); il.append(transf.loadHandler()); // The output handler il.append(new INVOKEVIRTUAL(topLevelIdx)); } // start document il.append(transf.loadHandler()); il.append(transf.startDocument()); // push first arg for applyTemplates il.append(classGen.loadTranslet()); // push translet for GETFIELD to get DOM arg il.append(classGen.loadTranslet()); il.append(new GETFIELD(domField)); // push remaining 2 args il.append(transf.loadIterator()); il.append(transf.loadHandler()); il.append(new INVOKEVIRTUAL(applyTemplates)); // endDocument il.append(transf.loadHandler()); il.append(transf.endDocument()); il.append(RETURN); // Compute max locals + stack and add method to class classGen.addMethod(transf); }
/** * This method is called when the constructor is compiled in Stylesheet.compileConstructor() and * not as the syntax tree is traversed. */ public void translate(ClassGenerator classGen, MethodGenerator methodGen) { ConstantPoolGen cpg = classGen.getConstantPool(); InstructionList il = methodGen.getInstructionList(); // DecimalFormatSymbols.<init>(Locale); // xsl:decimal-format - except for the NaN and infinity attributes. final int init = cpg.addMethodref(DFS_CLASS, "<init>", "(" + LOCALE_SIG + ")V"); // Push the format name on the stack for call to addDecimalFormat() il.append(classGen.loadTranslet()); il.append(new PUSH(cpg, _name.toString())); // Manufacture a DecimalFormatSymbols on the stack // for call to addDecimalFormat() // Use the US Locale as the default, as most of its settings // are equivalent to the default settings required of il.append(new NEW(cpg.addClass(DFS_CLASS))); il.append(DUP); il.append(new GETSTATIC(cpg.addFieldref(LOCALE_CLASS, "US", LOCALE_SIG))); il.append(new INVOKESPECIAL(init)); String tmp = getAttribute("NaN"); if ((tmp == null) || (tmp.equals(EMPTYSTRING))) { int nan = cpg.addMethodref(DFS_CLASS, "setNaN", "(Ljava/lang/String;)V"); il.append(DUP); il.append(new PUSH(cpg, "NaN")); il.append(new INVOKEVIRTUAL(nan)); } tmp = getAttribute("infinity"); if ((tmp == null) || (tmp.equals(EMPTYSTRING))) { int inf = cpg.addMethodref(DFS_CLASS, "setInfinity", "(Ljava/lang/String;)V"); il.append(DUP); il.append(new PUSH(cpg, "Infinity")); il.append(new INVOKEVIRTUAL(inf)); } final int nAttributes = _attributes.getLength(); for (int i = 0; i < nAttributes; i++) { final String name = _attributes.getQName(i); final String value = _attributes.getValue(i); boolean valid = true; int method = 0; if (name.equals("decimal-separator")) { // DecimalFormatSymbols.setDecimalSeparator(); method = cpg.addMethodref(DFS_CLASS, "setDecimalSeparator", "(C)V"); } else if (name.equals("grouping-separator")) { method = cpg.addMethodref(DFS_CLASS, "setGroupingSeparator", "(C)V"); } else if (name.equals("minus-sign")) { method = cpg.addMethodref(DFS_CLASS, "setMinusSign", "(C)V"); } else if (name.equals("percent")) { method = cpg.addMethodref(DFS_CLASS, "setPercent", "(C)V"); } else if (name.equals("per-mille")) { method = cpg.addMethodref(DFS_CLASS, "setPerMill", "(C)V"); } else if (name.equals("zero-digit")) { method = cpg.addMethodref(DFS_CLASS, "setZeroDigit", "(C)V"); } else if (name.equals("digit")) { method = cpg.addMethodref(DFS_CLASS, "setDigit", "(C)V"); } else if (name.equals("pattern-separator")) { method = cpg.addMethodref(DFS_CLASS, "setPatternSeparator", "(C)V"); } else if (name.equals("NaN")) { method = cpg.addMethodref(DFS_CLASS, "setNaN", "(Ljava/lang/String;)V"); il.append(DUP); il.append(new PUSH(cpg, value)); il.append(new INVOKEVIRTUAL(method)); valid = false; } else if (name.equals("infinity")) { method = cpg.addMethodref(DFS_CLASS, "setInfinity", "(Ljava/lang/String;)V"); il.append(DUP); il.append(new PUSH(cpg, value)); il.append(new INVOKEVIRTUAL(method)); valid = false; } else { valid = false; } if (valid) { il.append(DUP); il.append(new PUSH(cpg, value.charAt(0))); il.append(new INVOKEVIRTUAL(method)); } } final int put = cpg.addMethodref(TRANSLET_CLASS, "addDecimalFormat", "(" + STRING_SIG + DFS_SIG + ")V"); il.append(new INVOKEVIRTUAL(put)); }