|
|
|
|
|
*/ |
|
/* |
|
* 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 com.sun.org.apache.xalan.internal.xsltc.compiler; |
|
|
|
import com.sun.org.apache.bcel.internal.classfile.JavaClass; |
|
import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager; |
|
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; |
|
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util; |
|
import com.sun.org.apache.xml.internal.dtm.DTM; |
|
import java.io.ByteArrayOutputStream; |
|
import java.io.File; |
|
import java.io.FileOutputStream; |
|
import java.io.IOException; |
|
import java.io.InputStream; |
|
import java.net.URL; |
|
import java.util.ArrayList; |
|
import java.util.Collections; |
|
import java.util.Date; |
|
import java.util.HashMap; |
|
import java.util.List; |
|
import java.util.Map; |
|
import java.util.Objects; |
|
import java.util.Properties; |
|
import java.util.jar.Attributes; |
|
import java.util.jar.JarEntry; |
|
import java.util.jar.JarOutputStream; |
|
import java.util.jar.Manifest; |
|
import javax.xml.XMLConstants; |
|
import javax.xml.catalog.CatalogFeatures; |
|
import jdk.xml.internal.JdkConstants; |
|
import jdk.xml.internal.JdkXmlFeatures; |
|
import jdk.xml.internal.JdkXmlUtils; |
|
import jdk.xml.internal.SecuritySupport; |
|
import org.xml.sax.InputSource; |
|
import org.xml.sax.XMLReader; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public final class XSLTC { |
|
|
|
|
|
private Parser _parser; |
|
|
|
|
|
private XMLReader _reader = null; |
|
|
|
|
|
private SourceLoader _loader = null; |
|
|
|
|
|
private Stylesheet _stylesheet; |
|
|
|
// Counters used by various classes to generate unique names. |
|
|
|
private int _modeSerial = 1; |
|
private int _stylesheetSerial = 1; |
|
private int _stepPatternSerial = 1; |
|
private int _helperClassSerial = 0; |
|
private int _attributeSetSerial = 0; |
|
|
|
private int[] _numberFieldIndexes; |
|
|
|
// Name index tables |
|
private int _nextGType; |
|
private List<String> _namesIndex; |
|
private Map<String, Integer> _elements; |
|
private Map<String, Integer> _attributes; |
|
|
|
// Namespace index tables |
|
private int _nextNSType; |
|
private List<String> _namespaceIndex; |
|
private Map<String, Integer> _namespaces; |
|
private Map<String, Integer> _namespacePrefixes; |
|
|
|
|
|
|
|
private List<StringBuilder> m_characterData; |
|
|
|
|
|
public static final int JAR_OUTPUT = 1; |
|
public static final int BYTEARRAY_OUTPUT = 2; |
|
public static final int CLASSLOADER_OUTPUT = 3; |
|
public static final int BYTEARRAY_AND_FILE_OUTPUT = 4; |
|
public static final int BYTEARRAY_AND_JAR_OUTPUT = 5; |
|
|
|
|
|
// Compiler options (passed from command line or XSLTC client) |
|
private boolean _debug = false; |
|
private String _jarFileName = null; |
|
private String _className = null; |
|
private String _packageName = "die.verwandlung"; |
|
private File _destDir = null; |
|
private int _outputType = BYTEARRAY_OUTPUT; |
|
|
|
private List<ByteArrayOutputStream> _classes; |
|
private List<JavaClass> _bcelClasses; |
|
private boolean _callsNodeset = false; |
|
private boolean _multiDocument = false; |
|
private boolean _hasIdCall = false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private boolean _templateInlining = false; |
|
|
|
|
|
|
|
*/ |
|
private boolean _isSecureProcessing = false; |
|
|
|
private boolean _overrideDefaultParser; |
|
|
|
|
|
|
|
*/ |
|
private String _accessExternalStylesheet = JdkConstants.EXTERNAL_ACCESS_DEFAULT; |
|
|
|
|
|
*/ |
|
private String _accessExternalDTD = JdkConstants.EXTERNAL_ACCESS_DEFAULT; |
|
|
|
private XMLSecurityManager _xmlSecurityManager; |
|
|
|
private final JdkXmlFeatures _xmlFeatures; |
|
|
|
/** |
|
* Extension function class loader variables |
|
*/ |
|
|
|
|
|
private ClassLoader _extensionClassLoader; |
|
|
|
|
|
|
|
*/ |
|
private final Map<String, Class<?>> _externalExtensionFunctions; |
|
|
|
|
|
|
|
*/ |
|
CatalogFeatures _catalogFeatures; |
|
|
|
|
|
|
|
*/ |
|
int _cdataChunkSize; |
|
|
|
|
|
|
|
*/ |
|
public XSLTC(JdkXmlFeatures featureManager, boolean hasListener) { |
|
_overrideDefaultParser = featureManager.getFeature( |
|
JdkXmlFeatures.XmlFeature.JDK_OVERRIDE_PARSER); |
|
_parser = new Parser(this, _overrideDefaultParser, hasListener); |
|
_xmlFeatures = featureManager; |
|
_extensionClassLoader = null; |
|
_externalExtensionFunctions = new HashMap<>(); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void setSecureProcessing(boolean flag) { |
|
_isSecureProcessing = flag; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public boolean isSecureProcessing() { |
|
return _isSecureProcessing; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public boolean getFeature(JdkXmlFeatures.XmlFeature name) { |
|
return _xmlFeatures.getFeature(name); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public Object getProperty(String name) { |
|
if (name.equals(XMLConstants.ACCESS_EXTERNAL_STYLESHEET)) { |
|
return _accessExternalStylesheet; |
|
} |
|
else if (name.equals(XMLConstants.ACCESS_EXTERNAL_DTD)) { |
|
return _accessExternalDTD; |
|
} else if (name.equals(JdkConstants.SECURITY_MANAGER)) { |
|
return _xmlSecurityManager; |
|
} else if (name.equals(JdkConstants.JDK_EXT_CLASSLOADER)) { |
|
return _extensionClassLoader; |
|
} else if (JdkXmlFeatures.CATALOG_FEATURES.equals(name)) { |
|
return _catalogFeatures; |
|
} else if (JdkConstants.CDATA_CHUNK_SIZE.equals(name)) { |
|
return _cdataChunkSize; |
|
} |
|
return null; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void setProperty(String name, Object value) { |
|
if (name.equals(XMLConstants.ACCESS_EXTERNAL_STYLESHEET)) { |
|
_accessExternalStylesheet = (String)value; |
|
} |
|
else if (name.equals(XMLConstants.ACCESS_EXTERNAL_DTD)) { |
|
_accessExternalDTD = (String)value; |
|
} else if (name.equals(JdkConstants.SECURITY_MANAGER)) { |
|
_xmlSecurityManager = (XMLSecurityManager)value; |
|
} else if (name.equals(JdkConstants.JDK_EXT_CLASSLOADER)) { |
|
_extensionClassLoader = (ClassLoader) value; |
|
|
|
loader was changed */ |
|
_externalExtensionFunctions.clear(); |
|
} else if (JdkXmlFeatures.CATALOG_FEATURES.equals(name)) { |
|
_catalogFeatures = (CatalogFeatures)value; |
|
} else if (JdkConstants.CDATA_CHUNK_SIZE.equals(name)) { |
|
_cdataChunkSize = Integer.parseInt((String)value); |
|
} |
|
} |
|
|
|
|
|
|
|
*/ |
|
public Parser getParser() { |
|
return _parser; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void setOutputType(int type) { |
|
_outputType = type; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public Properties getOutputProperties() { |
|
return _parser.getOutputProperties(); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void init() { |
|
reset(); |
|
_reader = null; |
|
_classes = new ArrayList<>(); |
|
_bcelClasses = new ArrayList<>(); |
|
} |
|
|
|
private void setExternalExtensionFunctions(String name, Class<?> clazz) { |
|
if (_isSecureProcessing && clazz != null && !_externalExtensionFunctions.containsKey(name)) { |
|
_externalExtensionFunctions.put(name, clazz); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
Class<?> loadExternalFunction(String name) throws ClassNotFoundException { |
|
Class<?> loaded = null; |
|
|
|
if (_externalExtensionFunctions.containsKey(name)) { |
|
loaded = _externalExtensionFunctions.get(name); |
|
} else if (_extensionClassLoader != null) { |
|
loaded = Class.forName(name, true, _extensionClassLoader); |
|
setExternalExtensionFunctions(name, loaded); |
|
} |
|
if (loaded == null) { |
|
throw new ClassNotFoundException(name); |
|
} |
|
|
|
return loaded; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public Map<String, Class<?>> getExternalExtensionFunctions() { |
|
return Collections.unmodifiableMap(_externalExtensionFunctions); |
|
} |
|
|
|
|
|
|
|
*/ |
|
private void reset() { |
|
_nextGType = DTM.NTYPES; |
|
_elements = new HashMap<>(); |
|
_attributes = new HashMap<>(); |
|
_namespaces = new HashMap<>(); |
|
_namespaces.put("", _nextNSType); |
|
_namesIndex = new ArrayList<>(128); |
|
_namespaceIndex = new ArrayList<>(32); |
|
_namespacePrefixes = new HashMap<>(); |
|
_stylesheet = null; |
|
_parser.init(); |
|
|
|
_modeSerial = 1; |
|
_stylesheetSerial = 1; |
|
_stepPatternSerial = 1; |
|
_helperClassSerial = 0; |
|
_attributeSetSerial = 0; |
|
_multiDocument = false; |
|
_hasIdCall = false; |
|
_numberFieldIndexes = new int[] { |
|
-1, |
|
-1, |
|
-1 |
|
}; |
|
_externalExtensionFunctions.clear(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void setSourceLoader(SourceLoader loader) { |
|
_loader = loader; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void setTemplateInlining(boolean templateInlining) { |
|
_templateInlining = templateInlining; |
|
} |
|
|
|
|
|
*/ |
|
public boolean getTemplateInlining() { |
|
return _templateInlining; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void setPIParameters(String media, String title, String charset) { |
|
_parser.setPIParameters(media, title, charset); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public boolean compile(URL url) { |
|
try { |
|
|
|
final InputStream stream = url.openStream(); |
|
final InputSource input = new InputSource(stream); |
|
input.setSystemId(url.toString()); |
|
return compile(input, _className); |
|
} |
|
catch (IOException e) { |
|
_parser.reportError(Constants.FATAL, new ErrorMsg(ErrorMsg.JAXP_COMPILE_ERR, e)); |
|
return false; |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public boolean compile(URL url, String name) { |
|
try { |
|
|
|
final InputStream stream = url.openStream(); |
|
final InputSource input = new InputSource(stream); |
|
input.setSystemId(url.toString()); |
|
return compile(input, name); |
|
} |
|
catch (IOException e) { |
|
_parser.reportError(Constants.FATAL, new ErrorMsg(ErrorMsg.JAXP_COMPILE_ERR, e)); |
|
return false; |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public boolean compile(InputStream stream, String name) { |
|
final InputSource input = new InputSource(stream); |
|
input.setSystemId(name); |
|
return compile(input, name); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public boolean compile(InputSource input, String name) { |
|
try { |
|
|
|
reset(); |
|
|
|
|
|
String systemId = null; |
|
if (input != null) { |
|
systemId = input.getSystemId(); |
|
} |
|
|
|
|
|
if (_className == null) { |
|
if (name != null) { |
|
setClassName(name); |
|
} |
|
else if (systemId != null && !systemId.equals("")) { |
|
setClassName(Util.baseName(systemId)); |
|
} |
|
|
|
|
|
if (_className == null || _className.length() == 0) { |
|
setClassName("GregorSamsa"); |
|
} |
|
} |
|
|
|
|
|
SyntaxTreeNode element = null; |
|
if (_reader == null) { |
|
element = _parser.parse(input); |
|
} |
|
else { |
|
element = _parser.parse(_reader, input); |
|
} |
|
|
|
|
|
if ((!_parser.errorsFound()) && (element != null)) { |
|
|
|
_stylesheet = _parser.makeStylesheet(element); |
|
_stylesheet.setSourceLoader(_loader); |
|
_stylesheet.setSystemId(systemId); |
|
_stylesheet.setParentStylesheet(null); |
|
_stylesheet.setTemplateInlining(_templateInlining); |
|
_parser.setCurrentStylesheet(_stylesheet); |
|
|
|
|
|
_parser.createAST(_stylesheet); |
|
} |
|
|
|
if ((!_parser.errorsFound()) && (_stylesheet != null)) { |
|
_stylesheet.setCallsNodeset(_callsNodeset); |
|
_stylesheet.setMultiDocument(_multiDocument); |
|
_stylesheet.setHasIdCall(_hasIdCall); |
|
|
|
|
|
synchronized (getClass()) { |
|
_stylesheet.translate(); |
|
} |
|
} |
|
} |
|
catch (Exception e) { |
|
e.printStackTrace(); |
|
_parser.reportError(Constants.FATAL, new ErrorMsg(ErrorMsg.JAXP_COMPILE_ERR, e)); |
|
} |
|
catch (Error e) { |
|
if (_debug) e.printStackTrace(); |
|
_parser.reportError(Constants.FATAL, new ErrorMsg(ErrorMsg.JAXP_COMPILE_ERR, e)); |
|
} |
|
finally { |
|
_reader = null; |
|
} |
|
return !_parser.errorsFound(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public boolean compile(List<URL> stylesheets) { |
|
|
|
final int count = stylesheets.size(); |
|
|
|
|
|
if (count == 0) return true; |
|
|
|
// Special handling needed if the URL count is one, becuase the |
|
|
|
if (count == 1) { |
|
return compile(stylesheets.get(0)); |
|
} |
|
else { |
|
|
|
for (URL url : stylesheets) { |
|
_className = null; |
|
if (!compile(url)) return false; |
|
} |
|
} |
|
return true; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public byte[][] getBytecodes() { |
|
final int count = _classes.size(); |
|
final byte[][] result = new byte[count][1]; |
|
for (int i = 0; i < count; i++) |
|
result[i] = _classes.get(i).toByteArray(); |
|
return result; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public byte[][] compile(String name, InputSource input, int outputType) { |
|
_outputType = outputType; |
|
if (compile(input, name)) |
|
return getBytecodes(); |
|
else |
|
return null; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public byte[][] compile(String name, InputSource input) { |
|
return compile(name, input, BYTEARRAY_OUTPUT); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public void setXMLReader(XMLReader reader) { |
|
_reader = reader; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public XMLReader getXMLReader() { |
|
return _reader ; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public List<ErrorMsg> getErrors() { |
|
return _parser.getErrors(); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public List<ErrorMsg> getWarnings() { |
|
return _parser.getWarnings(); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void printErrors() { |
|
_parser.printErrors(); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void printWarnings() { |
|
_parser.printWarnings(); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
protected void setMultiDocument(boolean flag) { |
|
_multiDocument = flag; |
|
} |
|
|
|
public boolean isMultiDocument() { |
|
return _multiDocument; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
protected void setCallsNodeset(boolean flag) { |
|
if (flag) setMultiDocument(flag); |
|
_callsNodeset = flag; |
|
} |
|
|
|
public boolean callsNodeset() { |
|
return _callsNodeset; |
|
} |
|
|
|
protected void setHasIdCall(boolean flag) { |
|
_hasIdCall = flag; |
|
} |
|
|
|
public boolean hasIdCall() { |
|
return _hasIdCall; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void setClassName(String className) { |
|
final String base = Util.baseName(className); |
|
final String noext = Util.noExtName(base); |
|
String name = Util.toJavaName(noext); |
|
|
|
if (_packageName == null) |
|
_className = name; |
|
else |
|
_className = _packageName + '.' + name; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public String getClassName() { |
|
return _className; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
private String classFileName(final String className) { |
|
return className.replace('.', File.separatorChar) + ".class"; |
|
} |
|
|
|
|
|
|
|
*/ |
|
private File getOutputFile(String className) { |
|
if (_destDir != null) |
|
return new File(_destDir, classFileName(className)); |
|
else |
|
return new File(classFileName(className)); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public boolean setDestDirectory(String dstDirName) { |
|
final File dir = new File(dstDirName); |
|
if (SecuritySupport.doesFileExist(dir) || dir.mkdirs()) { |
|
_destDir = dir; |
|
return true; |
|
} |
|
else { |
|
_destDir = null; |
|
return false; |
|
} |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void setPackageName(String packageName) { |
|
_packageName = Objects.requireNonNull(packageName); |
|
if (_className != null) setClassName(_className); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public void setJarFileName(String jarFileName) { |
|
final String JAR_EXT = ".jar"; |
|
if (jarFileName.endsWith(JAR_EXT)) |
|
_jarFileName = jarFileName; |
|
else |
|
_jarFileName = jarFileName + JAR_EXT; |
|
_outputType = JAR_OUTPUT; |
|
} |
|
|
|
public String getJarFileName() { |
|
return _jarFileName; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void setStylesheet(Stylesheet stylesheet) { |
|
if (_stylesheet == null) _stylesheet = stylesheet; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public Stylesheet getStylesheet() { |
|
return _stylesheet; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public int registerAttribute(QName name) { |
|
Integer code = _attributes.get(name.toString()); |
|
if (code == null) { |
|
code = _nextGType++; |
|
_attributes.put(name.toString(), code); |
|
final String uri = name.getNamespace(); |
|
final String local = "@"+name.getLocalPart(); |
|
if ((uri != null) && (!uri.equals(""))) |
|
_namesIndex.add(uri+":"+local); |
|
else |
|
_namesIndex.add(local); |
|
if (name.getLocalPart().equals("*")) { |
|
registerNamespace(name.getNamespace()); |
|
} |
|
} |
|
return code.intValue(); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public int registerElement(QName name) { |
|
|
|
Integer code = _elements.get(name.toString()); |
|
if (code == null) { |
|
_elements.put(name.toString(), code = _nextGType++); |
|
_namesIndex.add(name.toString()); |
|
} |
|
if (name.getLocalPart().equals("*")) { |
|
registerNamespace(name.getNamespace()); |
|
} |
|
return code.intValue(); |
|
} |
|
|
|
/** |
|
* Registers a namespace prefix and gives it a type so that it can be mapped to |
|
* DOM namespace types at run-time. |
|
*/ |
|
|
|
public int registerNamespacePrefix(QName name) { |
|
|
|
Integer code = _namespacePrefixes.get(name.toString()); |
|
if (code == null) { |
|
code = _nextGType++; |
|
_namespacePrefixes.put(name.toString(), code); |
|
final String uri = name.getNamespace(); |
|
if ((uri != null) && (!uri.equals(""))){ |
|
|
|
_namesIndex.add("?"); |
|
} else{ |
|
_namesIndex.add("?"+name.getLocalPart()); |
|
} |
|
} |
|
return code.intValue(); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public int registerNamespace(String namespaceURI) { |
|
Integer code = _namespaces.get(namespaceURI); |
|
if (code == null) { |
|
code = _nextNSType++; |
|
_namespaces.put(namespaceURI,code); |
|
_namespaceIndex.add(namespaceURI); |
|
} |
|
return code; |
|
} |
|
|
|
public int nextModeSerial() { |
|
return _modeSerial++; |
|
} |
|
|
|
public int nextStylesheetSerial() { |
|
return _stylesheetSerial++; |
|
} |
|
|
|
public int nextStepPatternSerial() { |
|
return _stepPatternSerial++; |
|
} |
|
|
|
public int[] getNumberFieldIndexes() { |
|
return _numberFieldIndexes; |
|
} |
|
|
|
public int nextHelperClassSerial() { |
|
return _helperClassSerial++; |
|
} |
|
|
|
public int nextAttributeSetSerial() { |
|
return _attributeSetSerial++; |
|
} |
|
|
|
public List<String> getNamesIndex() { |
|
return _namesIndex; |
|
} |
|
|
|
public List<String> getNamespaceIndex() { |
|
return _namespaceIndex; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public String getHelperClassName() { |
|
return getClassName() + '$' + _helperClassSerial++; |
|
} |
|
|
|
public void dumpClass(JavaClass clazz) { |
|
|
|
if (_outputType == BYTEARRAY_AND_FILE_OUTPUT) |
|
{ |
|
File outFile = getOutputFile(clazz.getClassName()); |
|
String parentDir = outFile.getParent(); |
|
if (parentDir != null) { |
|
File parentFile = new File(parentDir); |
|
if (!SecuritySupport.doesFileExist(parentFile)) |
|
parentFile.mkdirs(); |
|
} |
|
} |
|
|
|
try { |
|
switch (_outputType) { |
|
case JAR_OUTPUT: |
|
_bcelClasses.add(clazz); |
|
break; |
|
case BYTEARRAY_OUTPUT: |
|
case BYTEARRAY_AND_FILE_OUTPUT: |
|
case BYTEARRAY_AND_JAR_OUTPUT: |
|
case CLASSLOADER_OUTPUT: |
|
ByteArrayOutputStream out = new ByteArrayOutputStream(2048); |
|
clazz.dump(out); |
|
_classes.add(out); |
|
|
|
if (_outputType == BYTEARRAY_AND_FILE_OUTPUT) |
|
clazz.dump(getOutputFile(clazz.getClassName())); |
|
else if (_outputType == BYTEARRAY_AND_JAR_OUTPUT) |
|
_bcelClasses.add(clazz); |
|
|
|
break; |
|
} |
|
} |
|
catch (Exception e) { |
|
e.printStackTrace(); |
|
} |
|
} |
|
|
|
|
|
|
|
*/ |
|
private String entryName(File f) throws IOException { |
|
return f.getName().replace(File.separatorChar, '/'); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void outputToJar() throws IOException { |
|
|
|
final Manifest manifest = new Manifest(); |
|
final java.util.jar.Attributes atrs = manifest.getMainAttributes(); |
|
atrs.put(java.util.jar.Attributes.Name.MANIFEST_VERSION, "1.2"); |
|
|
|
final Map<String, Attributes> map = manifest.getEntries(); |
|
|
|
final String now = (new Date()).toString(); |
|
final java.util.jar.Attributes.Name dateAttr = |
|
new java.util.jar.Attributes.Name("Date"); |
|
|
|
final File jarFile = new File(_destDir, _jarFileName); |
|
final JarOutputStream jos = |
|
new JarOutputStream(new FileOutputStream(jarFile), manifest); |
|
|
|
for (JavaClass clazz : _bcelClasses) { |
|
final String className = clazz.getClassName().replace('.', '/'); |
|
final java.util.jar.Attributes attr = new java.util.jar.Attributes(); |
|
attr.put(dateAttr, now); |
|
map.put(className + ".class", attr); |
|
jos.putNextEntry(new JarEntry(className + ".class")); |
|
final ByteArrayOutputStream out = new ByteArrayOutputStream(2048); |
|
clazz.dump(out); |
|
out.writeTo(jos); |
|
} |
|
jos.close(); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void setDebug(boolean debug) { |
|
_debug = debug; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public boolean debug() { |
|
return _debug; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public String getCharacterData(int index) { |
|
return (m_characterData.get(index)).toString(); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public int getCharacterDataCount() { |
|
return (m_characterData != null) ? m_characterData.size() : 0; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public int addCharacterData(String newData) { |
|
StringBuilder currData; |
|
if (m_characterData == null) { |
|
m_characterData = new ArrayList<>(); |
|
currData = new StringBuilder(); |
|
m_characterData.add(currData); |
|
} else { |
|
currData = m_characterData.get(m_characterData.size()-1); |
|
} |
|
|
|
// Character data could take up to three-times as much space when |
|
// written to the class file as UTF-8. The maximum size for a |
|
// constant is 65535/3. If we exceed that, |
|
|
|
if (newData.length() + currData.length() > 21845) { |
|
currData = new StringBuilder(); |
|
m_characterData.add(currData); |
|
} |
|
|
|
int newDataOffset = currData.length(); |
|
currData.append(newData); |
|
|
|
return newDataOffset; |
|
} |
|
} |