diff options
| author | Joshua Peek <josh@joshpeek.com> | 2012-07-23 15:52:49 -0500 |
|---|---|---|
| committer | Joshua Peek <josh@joshpeek.com> | 2012-07-23 15:52:49 -0500 |
| commit | 7b6caa0f6c7603aabb5e6ed657e24aaddbeafc78 (patch) | |
| tree | ec0522eae75bb04ae73d28ae3f599682a2bfdaeb /samples/Java | |
| parent | 314f0e485227915931db361be14d308a210bedea (diff) | |
Rename samples subdirectories
Diffstat (limited to 'samples/Java')
| -rw-r--r-- | samples/Java/HtmlDomParserContext.java | 243 | ||||
| -rw-r--r-- | samples/Java/Hudson.java | 322 | ||||
| -rw-r--r-- | samples/Java/NokogiriService.java | 598 | ||||
| -rw-r--r-- | samples/Java/clojure-type.java | 872 | ||||
| -rw-r--r-- | samples/Java/clojure-util.java | 197 |
5 files changed, 2232 insertions, 0 deletions
diff --git a/samples/Java/HtmlDomParserContext.java b/samples/Java/HtmlDomParserContext.java new file mode 100644 index 0000000..6c13e3d --- /dev/null +++ b/samples/Java/HtmlDomParserContext.java @@ -0,0 +1,243 @@ +/** + * (The MIT License) + * + * Copyright (c) 2008 - 2012: + * + * * {Aaron Patterson}[http://tenderlovemaking.com] + * * {Mike Dalessio}[http://mike.daless.io] + * * {Charles Nutter}[http://blog.headius.com] + * * {Sergio Arbeo}[http://www.serabe.com] + * * {Patrick Mahoney}[http://polycrystal.org] + * * {Yoko Harada}[http://yokolet.blogspot.com] + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * 'Software'), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package nokogiri.internals; + +import static nokogiri.internals.NokogiriHelpers.getNokogiriClass; +import static nokogiri.internals.NokogiriHelpers.isNamespace; +import static nokogiri.internals.NokogiriHelpers.stringOrNil; +import nokogiri.HtmlDocument; +import nokogiri.NokogiriService; +import nokogiri.XmlDocument; + +import org.apache.xerces.parsers.DOMParser; +import org.apache.xerces.xni.Augmentations; +import org.apache.xerces.xni.QName; +import org.apache.xerces.xni.XMLAttributes; +import org.apache.xerces.xni.XNIException; +import org.apache.xerces.xni.parser.XMLDocumentFilter; +import org.apache.xerces.xni.parser.XMLParserConfiguration; +import org.cyberneko.html.HTMLConfiguration; +import org.cyberneko.html.filters.DefaultFilter; +import org.jruby.Ruby; +import org.jruby.RubyClass; +import org.jruby.runtime.ThreadContext; +import org.jruby.runtime.builtin.IRubyObject; +import org.w3c.dom.Document; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.NodeList; + +/** + * Parser for HtmlDocument. This class actually parses HtmlDocument using NekoHtml. + * + * @author sergio + * @author Patrick Mahoney <pat@polycrystal.org> + * @author Yoko Harada <yokolet@gmail.com> + */ +public class HtmlDomParserContext extends XmlDomParserContext { + + public HtmlDomParserContext(Ruby runtime, IRubyObject options) { + super(runtime, options); + } + + public HtmlDomParserContext(Ruby runtime, IRubyObject encoding, IRubyObject options) { + super(runtime, encoding, options); + } + + @Override + protected void initErrorHandler() { + if (options.strict) { + errorHandler = new NokogiriStrictErrorHandler(options.noError, options.noWarning); + } else { + errorHandler = new NokogiriNonStrictErrorHandler4NekoHtml(options.noError, options.noWarning); + } + } + + @Override + protected void initParser(Ruby runtime) { + XMLParserConfiguration config = new HTMLConfiguration(); + XMLDocumentFilter removeNSAttrsFilter = new RemoveNSAttrsFilter(); + XMLDocumentFilter elementValidityCheckFilter = new ElementValidityCheckFilter(errorHandler); + //XMLDocumentFilter[] filters = { removeNSAttrsFilter, elementValidityCheckFilter}; + XMLDocumentFilter[] filters = { elementValidityCheckFilter}; + + config.setErrorHandler(this.errorHandler); + parser = new DOMParser(config); + + // see http://nekohtml.sourceforge.net/settings.html for details + setProperty("http://cyberneko.org/html/properties/default-encoding", java_encoding); + setProperty("http://cyberneko.org/html/properties/names/elems", "lower"); + setProperty("http://cyberneko.org/html/properties/names/attrs", "lower"); + setProperty("http://cyberneko.org/html/properties/filters", filters); + setFeature("http://cyberneko.org/html/features/report-errors", true); + setFeature("http://xml.org/sax/features/namespaces", false); + setFeature("http://cyberneko.org/html/features/insert-doctype", true); + } + + /** + * Enable NekoHTML feature for balancing tags in a document fragment. + * + * This method is used in XmlNode#in_context method. + */ + public void enableDocumentFragment() { + setFeature("http://cyberneko.org/html/features/balance-tags/document-fragment", true); + } + + @Override + protected XmlDocument getNewEmptyDocument(ThreadContext context) { + IRubyObject[] args = new IRubyObject[0]; + return (XmlDocument) XmlDocument.rbNew(context, getNokogiriClass(context.getRuntime(), "Nokogiri::HTML::Document"), args); + } + + @Override + protected XmlDocument wrapDocument(ThreadContext context, + RubyClass klazz, + Document document) { + HtmlDocument htmlDocument = (HtmlDocument) NokogiriService.HTML_DOCUMENT_ALLOCATOR.allocate(context.getRuntime(), klazz); + htmlDocument.setDocumentNode(context, document); + if (ruby_encoding.isNil()) { + // ruby_encoding might have detected by HtmlDocument::EncodingReader + if (detected_encoding != null && !detected_encoding.isNil()) { + ruby_encoding = detected_encoding; + } else { + // no encoding given & no encoding detected, then try to get it + String charset = tryGetCharsetFromHtml5MetaTag(document); + ruby_encoding = stringOrNil(context.getRuntime(), charset); + } + } + htmlDocument.setEncoding(ruby_encoding); + htmlDocument.setParsedEncoding(java_encoding); + return htmlDocument; + } + + // NekoHtml doesn't understand HTML5 meta tag format. This fails to detect charset + // from an HTML5 style meta tag. Luckily, the meta tag and charset exists in DOM tree + // so, this method attempts to find the charset. + private String tryGetCharsetFromHtml5MetaTag(Document document) { + if (!"html".equalsIgnoreCase(document.getDocumentElement().getNodeName())) return null; + NodeList list = document.getDocumentElement().getChildNodes(); + for (int i = 0; i < list.getLength(); i++) { + if ("head".equalsIgnoreCase(list.item(i).getNodeName())) { + NodeList headers = list.item(i).getChildNodes(); + for (int j = 0; j < headers.getLength(); j++) { + if ("meta".equalsIgnoreCase(headers.item(j).getNodeName())) { + NamedNodeMap nodeMap = headers.item(j).getAttributes(); + for (int k = 0; k < nodeMap.getLength(); k++) { + if ("charset".equalsIgnoreCase(nodeMap.item(k).getNodeName())) { + return nodeMap.item(k).getNodeValue(); + } + } + } + } + } + } + return null; + } + + /** + * Filter to strip out attributes that pertain to XML namespaces. + */ + public static class RemoveNSAttrsFilter extends DefaultFilter { + @Override + public void startElement(QName element, XMLAttributes attrs, + Augmentations augs) throws XNIException { + int i; + for (i = 0; i < attrs.getLength(); ++i) { + if (isNamespace(attrs.getQName(i))) { + attrs.removeAttributeAt(i); + --i; + } + } + + element.uri = null; + super.startElement(element, attrs, augs); + } + } + + public static class ElementValidityCheckFilter extends DefaultFilter { + private NokogiriErrorHandler errorHandler; + + private ElementValidityCheckFilter(NokogiriErrorHandler errorHandler) { + this.errorHandler = errorHandler; + } + + // element names from xhtml1-strict.dtd + private static String[][] element_names = { + {"a", "abbr", "acronym", "address", "area"}, + {"b", "base", "basefont", "bdo", "big", "blockquote", "body", "br", "button"}, + {"caption", "cite", "code", "col", "colgroup"}, + {"dd", "del", "dfn", "div", "dl", "dt"}, + {"em"}, + {"fieldset", "font", "form", "frame", "frameset"}, + {}, // g + {"h1", "h2", "h3", "h4", "h5", "h6", "head", "hr", "html"}, + {"i", "iframe", "img", "input", "ins"}, + {}, // j + {"kbd"}, + {"label", "legend", "li", "link"}, + {"map", "meta"}, + {"noframes", "noscript"}, + {"object", "ol", "optgroup", "option"}, + {"p", "param", "pre"}, + {"q"}, + {}, // r + {"s", "samp", "script", "select", "small", "span", "strike", "strong", "style", "sub", "sup"}, + {"table", "tbody", "td", "textarea", "tfoot", "th", "thead", "title", "tr", "tt"}, + {"u", "ul"}, + {"var"}, + {}, // w + {}, // x + {}, // y + {} // z + }; + + private boolean isValid(String testee) { + char[] c = testee.toCharArray(); + int index = new Integer(c[0]) - 97; + if (index > 25) return false; + for (int i=0; i<element_names[index].length; i++) { + if (testee.equals(element_names[index][i])) { + return true; + } + } + return false; + } + + @Override + public void startElement(QName name, XMLAttributes attrs, Augmentations augs) throws XNIException { + if (!isValid(name.rawname)) { + errorHandler.getErrors().add(new Exception("Tag " + name.rawname + " invalid")); + } + super.startElement(name, attrs, augs); + } + } +} diff --git a/samples/Java/Hudson.java b/samples/Java/Hudson.java new file mode 100644 index 0000000..aff8df4 --- /dev/null +++ b/samples/Java/Hudson.java @@ -0,0 +1,322 @@ +/* + * The MIT License + * + * Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi, + * Erik Ramfelt, Koichi Fujikawa, Red Hat, Inc., Seiji Sogabe, + * Stephen Connolly, Tom Huybrechts, Yahoo! Inc., Alan Harder, CloudBees, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package hudson.model; + +import hudson.ExtensionListView; +import hudson.Functions; +import hudson.Platform; +import hudson.PluginManager; +import hudson.cli.declarative.CLIResolver; +import hudson.model.listeners.ItemListener; +import hudson.slaves.ComputerListener; +import hudson.util.CopyOnWriteList; +import hudson.util.FormValidation; +import jenkins.model.Jenkins; +import org.jvnet.hudson.reactor.ReactorException; +import org.kohsuke.stapler.QueryParameter; +import org.kohsuke.stapler.Stapler; +import org.kohsuke.stapler.StaplerRequest; +import org.kohsuke.stapler.StaplerResponse; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import java.io.File; +import java.io.IOException; +import java.text.NumberFormat; +import java.text.ParseException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static hudson.Util.fixEmpty; + +public class Hudson extends Jenkins { + + /** + * List of registered {@link hudson.model.listeners.ItemListener}s. + * @deprecated as of 1.286 + */ + private transient final CopyOnWriteList<ItemListener> itemListeners = ExtensionListView.createCopyOnWriteList(ItemListener.class); + + /** + * List of registered {@link hudson.slaves.ComputerListener}s. + * @deprecated as of 1.286 + */ + private transient final CopyOnWriteList<ComputerListener> computerListeners = ExtensionListView.createCopyOnWriteList(ComputerListener.class); + + + @CLIResolver + public static Hudson getInstance() { + return (Hudson)Jenkins.getInstance(); + } + + public Hudson(File root, ServletContext context) throws IOException, InterruptedException, ReactorException { + this(root,context,null); + } + + public Hudson(File root, ServletContext context, PluginManager pluginManager) throws IOException, InterruptedException, ReactorException { + super(root, context, pluginManager); + } + + /** + * Gets all the installed {@link ItemListener}s. + * + * @deprecated as of 1.286. + * Use {@link ItemListener#all()}. + */ + public CopyOnWriteList<ItemListener> getJobListeners() { + return itemListeners; + } + + /** + * Gets all the installed {@link ComputerListener}s. + * + * @deprecated as of 1.286. + * Use {@link ComputerListener#all()}. + */ + public CopyOnWriteList<ComputerListener> getComputerListeners() { + return computerListeners; + } + + /** + * Gets the slave node of the give name, hooked under this Hudson. + * + * @deprecated + * Use {@link #getNode(String)}. Since 1.252. + */ + public Slave getSlave(String name) { + Node n = getNode(name); + if (n instanceof Slave) + return (Slave)n; + return null; + } + + /** + * @deprecated + * Use {@link #getNodes()}. Since 1.252. + */ + public List<Slave> getSlaves() { + return (List)slaves; + } + + /** + * Updates the slave list. + * + * @deprecated + * Use {@link #setNodes(List)}. Since 1.252. + */ + public void setSlaves(List<Slave> slaves) throws IOException { + setNodes(slaves); + } + + /** + * @deprecated + * Left only for the compatibility of URLs. + * Should not be invoked for any other purpose. + */ + public TopLevelItem getJob(String name) { + return getItem(name); + } + + /** + * @deprecated + * Used only for mapping jobs to URL in a case-insensitive fashion. + */ + public TopLevelItem getJobCaseInsensitive(String name) { + String match = Functions.toEmailSafeString(name); + for(TopLevelItem item : getItems()) { + if(Functions.toEmailSafeString(item.getName()).equalsIgnoreCase(match)) { + return item; + } + } + return null; + } + + /** + * @deprecated as of 1.317 + * Use {@link #doQuietDown()} instead. + */ + public synchronized void doQuietDown(StaplerResponse rsp) throws IOException, ServletException { + doQuietDown().generateResponse(null, rsp, this); + } + + /** + * RSS feed for log entries. + * + * @deprecated + * As on 1.267, moved to "/log/rss..." + */ + public void doLogRss( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException { + String qs = req.getQueryString(); + rsp.sendRedirect2("./log/rss"+(qs==null?"":'?'+qs)); + } + + /** + * @deprecated as of 1.294 + * Define your own check method, instead of relying on this generic one. + */ + public void doFieldCheck(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { + doFieldCheck( + fixEmpty(req.getParameter("value")), + fixEmpty(req.getParameter("type")), + fixEmpty(req.getParameter("errorText")), + fixEmpty(req.getParameter("warningText"))).generateResponse(req,rsp,this); + } + + /** + * Checks if the value for a field is set; if not an error or warning text is displayed. + * If the parameter "value" is not set then the parameter "errorText" is displayed + * as an error text. If the parameter "errorText" is not set, then the parameter "warningText" + * is displayed as a warning text. + * <p> + * If the text is set and the parameter "type" is set, it will validate that the value is of the + * correct type. Supported types are "number, "number-positive" and "number-negative". + * + * @deprecated as of 1.324 + * Either use client-side validation (e.g. class="required number") + * or define your own check method, instead of relying on this generic one. + */ + public FormValidation doFieldCheck(@QueryParameter(fixEmpty=true) String value, + @QueryParameter(fixEmpty=true) String type, + @QueryParameter(fixEmpty=true) String errorText, + @QueryParameter(fixEmpty=true) String warningText) { + if (value == null) { + if (errorText != null) + return FormValidation.error(errorText); + if (warningText != null) + return FormValidation.warning(warningText); + return FormValidation.error("No error or warning text was set for fieldCheck()."); + } + + if (type != null) { + try { + if (type.equalsIgnoreCase("number")) { + NumberFormat.getInstance().parse(value); + } else if (type.equalsIgnoreCase("number-positive")) { + if (NumberFormat.getInstance().parse(value).floatValue() <= 0) + return FormValidation.error(Messages.Hudson_NotAPositiveNumber()); + } else if (type.equalsIgnoreCase("number-negative")) { + if (NumberFormat.getInstance().parse(value).floatValue() >= 0) + return FormValidation.error(Messages.Hudson_NotANegativeNumber()); + } + } catch (ParseException e) { + return FormValidation.error(Messages.Hudson_NotANumber()); + } + } + + return FormValidation.ok(); + } + + /** + * @deprecated + * Use {@link Functions#isWindows()}. + */ + public static boolean isWindows() { + return File.pathSeparatorChar==';'; + } + + /** + * @deprecated + * Use {@link hudson.Platform#isDarwin()} + */ + public static boolean isDarwin() { + return Platform.isDarwin(); + } + + /** + * @deprecated since 2007-12-18. + * Use {@link #checkPermission(hudson.security.Permission)} + */ + public static boolean adminCheck() throws IOException { + return adminCheck(Stapler.getCurrentRequest(), Stapler.getCurrentResponse()); + } + + /** + * @deprecated since 2007-12-18. + * Use {@link #checkPermission(hudson.security.Permission)} + */ + public static boolean adminCheck(StaplerRequest req,StaplerResponse rsp) throws IOException { + if (isAdmin(req)) return true; + + rsp.sendError(StaplerResponse.SC_FORBIDDEN); + return false; + } + + /** + * Checks if the current user (for which we are processing the current request) + * has the admin access. + * + * @deprecated since 2007-12-18. + * This method is deprecated when Hudson moved from simple Unix root-like model + * of "admin gets to do everything, and others don't have any privilege" to more + * complex {@link hudson.security.ACL} and {@link hudson.security.Permission} based scheme. + * + * <p> + * For a quick migration, use {@code Hudson.getInstance().getACL().hasPermission(Hudson.ADMINISTER)} + * To check if the user has the 'administer' role in Hudson. + * + * <p> + * But ideally, your plugin should first identify a suitable {@link hudson.security.Permission} (or create one, + * if appropriate), then identify a suitable {@link hudson.security.AccessControlled} object to check its permission + * against. + */ + public static boolean isAdmin() { + return Jenkins.getInstance().getACL().hasPermission(ADMINISTER); + } + + /** + * @deprecated since 2007-12-18. + * Define a custom {@link hudson.security.Permission} and check against ACL. + * See {@link #isAdmin()} for more instructions. + */ + public static boolean isAdmin(StaplerRequest req) { + return isAdmin(); + } + + static { + XSTREAM.alias("hudson",Hudson.class); + } + + /** + * @deprecated only here for backward comp + */ + public static final class MasterComputer extends Jenkins.MasterComputer { + // no op + } + + /** + * @deprecated only here for backward comp + */ + public static class CloudList extends Jenkins.CloudList { + public CloudList(Jenkins h) { + super(h); + } + + public CloudList() {// needed for XStream deserialization + super(); + } + } +} diff --git a/samples/Java/NokogiriService.java b/samples/Java/NokogiriService.java new file mode 100644 index 0000000..b497675 --- /dev/null +++ b/samples/Java/NokogiriService.java @@ -0,0 +1,598 @@ +/** + * (The MIT License) + * + * Copyright (c) 2008 - 2011: + * + * * {Aaron Patterson}[http://tenderlovemaking.com] + * * {Mike Dalessio}[http://mike.daless.io] + * * {Charles Nutter}[http://blog.headius.com] + * * {Sergio Arbeo}[http://www.serabe.com] + * * {Patrick Mahoney}[http://polycrystal.org] + * * {Yoko Harada}[http://yokolet.blogspot.com] + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * 'Software'), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package nokogiri; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.jruby.Ruby; +import org.jruby.RubyArray; +import org.jruby.RubyClass; +import org.jruby.RubyFixnum; +import org.jruby.RubyModule; +import org.jruby.runtime.ObjectAllocator; +import org.jruby.runtime.builtin.IRubyObject; +import org.jruby.runtime.load.BasicLibraryService; + +/** + * Class to provide Nokogiri. This class is used to make "require 'nokogiri'" work + * in JRuby. Also, this class holds a Ruby type cache and allocators of Ruby types. + * + * @author headius + * @author Yoko Harada <yokolet@gmail.com> + */ +public class NokogiriService implements BasicLibraryService { + public static final String nokogiriClassCacheGvarName = "$NOKOGIRI_CLASS_CACHE"; + public static Map<String, RubyClass> nokogiriClassCache; + + public boolean basicLoad(Ruby ruby) { + init(ruby); + createNokogiriClassCahce(ruby); + return true; + } + + private static void createNokogiriClassCahce(Ruby ruby) { + nokogiriClassCache = Collections.synchronizedMap(new HashMap<String, RubyClass>()); + nokogiriClassCache.put("Nokogiri::EncodingHandler", (RubyClass)ruby.getClassFromPath("Nokogiri::EncodingHandler")); + nokogiriClassCache.put("Nokogiri::HTML::Document", (RubyClass)ruby.getClassFromPath("Nokogiri::HTML::Document")); + nokogiriClassCache.put("Nokogiri::HTML::ElementDescription", (RubyClass)ruby.getClassFromPath("Nokogiri::HTML::ElementDescription")); + nokogiriClassCache.put("Nokogiri::XML::Attr", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::Attr")); + nokogiriClassCache.put("Nokogiri::XML::Document", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::Document")); + nokogiriClassCache.put("Nokogiri::XML::DocumentFragment", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::DocumentFragment")); + nokogiriClassCache.put("Nokogiri::XML::DTD", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::DTD")); + nokogiriClassCache.put("Nokogiri::XML::Text", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::Text")); + nokogiriClassCache.put("Nokogiri::XML::Comment", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::Comment")); + nokogiriClassCache.put("Nokogiri::XML::Element", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::Element")); + nokogiriClassCache.put("Nokogiri::XML::ElementContent", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::ElementContent")); + nokogiriClassCache.put("Nokogiri::XML::ElementDecl", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::ElementDecl")); + nokogiriClassCache.put("Nokogiri::XML::EntityDecl", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::EntityDecl")); + nokogiriClassCache.put("Nokogiri::XML::EntityReference", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::EntityReference")); + nokogiriClassCache.put("Nokogiri::XML::ProcessingInstruction", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::ProcessingInstruction")); + nokogiriClassCache.put("Nokogiri::XML::CDATA", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::CDATA")); + nokogiriClassCache.put("Nokogiri::XML::Node", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::Node")); + nokogiriClassCache.put("Nokogiri::XML::NodeSet", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::NodeSet")); + nokogiriClassCache.put("Nokogiri::XML::Namespace", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::Namespace")); + nokogiriClassCache.put("Nokogiri::XML::SyntaxError", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::SyntaxError")); + nokogiriClassCache.put("Nokogiri::XML::Reader", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::Reader")); + nokogiriClassCache.put("Nokogiri::XML::RelaxNG", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::RelaxNG")); + nokogiriClassCache.put("Nokogiri::XML::Schema", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::Schema")); + nokogiriClassCache.put("Nokogiri::XML::XPathContext", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::XPathContext")); + nokogiriClassCache.put("Nokogiri::XML::AttributeDecl", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::AttributeDecl")); + nokogiriClassCache.put("Nokogiri::XML::SAX::ParserContext", (RubyClass)ruby.getClassFromPath("Nokogiri::XML::SAX::ParserContext")); + } + + private void init(Ruby ruby) { + RubyModule nokogiri = ruby.defineModule("Nokogiri"); + RubyModule xmlModule = nokogiri.defineModuleUnder("XML"); + RubyModule xmlSaxModule = xmlModule.defineModuleUnder("SAX"); + RubyModule htmlModule = nokogiri.defineModuleUnder("HTML"); + RubyModule htmlSaxModule = htmlModule.defineModuleUnder("SAX"); + RubyModule xsltModule = nokogiri.defineModuleUnder("XSLT"); + + createNokogiriModule(ruby, nokogiri); + createSyntaxErrors(ruby, nokogiri, xmlModule); + RubyClass xmlNode = createXmlModule(ruby, xmlModule); + createHtmlModule(ruby, htmlModule); + createDocuments(ruby, xmlModule, htmlModule, xmlNode); + createSaxModule(ruby, xmlSaxModule, htmlSaxModule); + createXsltModule(ruby, xsltModule); + } + + private void createNokogiriModule(Ruby ruby, RubyModule nokogiri) {; + RubyClass encHandler = nokogiri.defineClassUnder("EncodingHandler", ruby.getObject(), ENCODING_HANDLER_ALLOCATOR); + encHandler.defineAnnotatedMethods(EncodingHandler.class); + } + + private void createSyntaxErrors(Ruby ruby, RubyModule nokogiri, RubyModule xmlModule) { + RubyClass syntaxError = nokogiri.defineClassUnder("SyntaxError", ruby.getStandardError(), ruby.getStandardError().getAllocator()); + RubyClass xmlSyntaxError = xmlModule.defineClassUnder("SyntaxError", syntaxError, XML_SYNTAXERROR_ALLOCATOR); + xmlSyntaxError.defineAnnotatedMethods(XmlSyntaxError.class); + } + + private RubyClass createXmlModule(Ruby ruby, RubyModule xmlModule) { + RubyClass node = xmlModule.defineClassUnder("Node", ruby.getObject(), XML_NODE_ALLOCATOR); + node.defineAnnotatedMethods(XmlNode.class); + + RubyClass attr = xmlModule.defineClassUnder("Attr", node, XML_ATTR_ALLOCATOR); + attr.defineAnnotatedMethods(XmlAttr.class); + + RubyClass attrDecl = xmlModule.defineClassUnder("AttributeDecl", node, XML_ATTRIBUTE_DECL_ALLOCATOR); + attrDecl.defineAnnotatedMethods(XmlAttributeDecl.class); + + RubyClass characterData = xmlModule.defineClassUnder("CharacterData", node, null); + + RubyClass comment = xmlModule.defineClassUnder("Comment", characterData, XML_COMMENT_ALLOCATOR); + comment.defineAnnotatedMethods(XmlComment.class); + + RubyClass text = xmlModule.defineClassUnder("Text", characterData, XML_TEXT_ALLOCATOR); + text.defineAnnotatedMethods(XmlText.class); + + RubyModule cdata = xmlModule.defineClassUnder("CDATA", text, XML_CDATA_ALLOCATOR); + cdata.defineAnnotatedMethods(XmlCdata.class); + + RubyClass dtd = xmlModule.defineClassUnder("DTD", node, XML_DTD_ALLOCATOR); + dtd.defineAnnotatedMethods(XmlDtd.class); + + RubyClass documentFragment = xmlModule.defineClassUnder("DocumentFragment", node, XML_DOCUMENT_FRAGMENT_ALLOCATOR); + documentFragment.defineAnnotatedMethods(XmlDocumentFragment.class); + + RubyClass element = xmlModule.defineClassUnder("Element", node, XML_ELEMENT_ALLOCATOR); + element.defineAnnotatedMethods(XmlElement.class); + + RubyClass elementContent = xmlModule.defineClassUnder("ElementContent", ruby.getObject(), XML_ELEMENT_CONTENT_ALLOCATOR); + elementContent.defineAnnotatedMethods(XmlElementContent.class); + + RubyClass elementDecl = xmlModule.defineClassUnder("ElementDecl", node, XML_ELEMENT_DECL_ALLOCATOR); + elementDecl.defineAnnotatedMethods(XmlElementDecl.class); + + RubyClass entityDecl = xmlModule.defineClassUnder("EntityDecl", node, XML_ENTITY_DECL_ALLOCATOR); + entityDecl.defineAnnotatedMethods(XmlEntityDecl.class); + + entityDecl.defineConstant("INTERNAL_GENERAL", RubyFixnum.newFixnum(ruby, XmlEntityDecl.INTERNAL_GENERAL)); + entityDecl.defineConstant("EXTERNAL_GENERAL_PARSED", RubyFixnum.newFixnum(ruby, XmlEntityDecl.EXTERNAL_GENERAL_PARSED)); + entityDecl.defineConstant("EXTERNAL_GENERAL_UNPARSED", RubyFixnum.newFixnum(ruby, XmlEntityDecl.EXTERNAL_GENERAL_UNPARSED)); + entityDecl.defineConstant("INTERNAL_PARAMETER", RubyFixnum.newFixnum(ruby, XmlEntityDecl.INTERNAL_PARAMETER)); + entityDecl.defineConstant("EXTERNAL_PARAMETER", RubyFixnum.newFixnum(ruby, XmlEntityDecl.EXTERNAL_PARAMETER)); + entityDecl.defineConstant("INTERNAL_PREDEFINED", RubyFixnum.newFixnum(ruby, XmlEntityDecl.INTERNAL_PREDEFINED)); + + RubyClass entref = xmlModule.defineClassUnder("EntityReference", node, XML_ENTITY_REFERENCE_ALLOCATOR); + entref.defineAnnotatedMethods(XmlEntityReference.class); + + RubyClass namespace = xmlModule.defineClassUnder("Namespace", ruby.getObject(), XML_NAMESPACE_ALLOCATOR); + namespace.defineAnnotatedMethods(XmlNamespace.class); + + RubyClass nodeSet = xmlModule.defineClassUnder("NodeSet", ruby.getObject(), XML_NODESET_ALLOCATOR); + nodeSet.defineAnnotatedMethods(XmlNodeSet.class); + + RubyClass pi = xmlModule.defineClassUnder("ProcessingInstruction", node, XML_PROCESSING_INSTRUCTION_ALLOCATOR); + pi.defineAnnotatedMethods(XmlProcessingInstruction.class); + + RubyClass reader = xmlModule.defineClassUnder("Reader", ruby.getObject(), XML_READER_ALLOCATOR); + reader.defineAnnotatedMethods(XmlReader.class); + + RubyClass schema = xmlModule.defineClassUnder("Schema", ruby.getObject(), XML_SCHEMA_ALLOCATOR); + schema.defineAnnotatedMethods(XmlSchema.class); + + RubyClass relaxng = xmlModule.defineClassUnder("RelaxNG", schema, XML_RELAXNG_ALLOCATOR); + relaxng.defineAnnotatedMethods(XmlRelaxng.class); + + RubyClass xpathContext = xmlModule.defineClassUnder("XPathContext", ruby.getObject(), XML_XPATHCONTEXT_ALLOCATOR); + xpathContext.defineAnnotatedMethods(XmlXpathContext.class); + + return node; + } + + private void createHtmlModule(Ruby ruby, RubyModule htmlModule) { + RubyClass htmlElemDesc = htmlModule.defineClassUnder("ElementDescription", ruby.getObject(), HTML_ELEMENT_DESCRIPTION_ALLOCATOR); + htmlElemDesc.defineAnnotatedMethods(HtmlElementDescription.class); + + RubyClass htmlEntityLookup = htmlModule.defineClassUnder("EntityLookup", ruby.getObject(), HTML_ENTITY_LOOKUP_ALLOCATOR); + htmlEntityLookup.defineAnnotatedMethods(HtmlEntityLookup.class); + } + + private void createDocuments(Ruby ruby, RubyModule xmlModule, RubyModule htmlModule, RubyClass node) { + RubyClass xmlDocument = xmlModule.defineClassUnder("Document", node, XML_DOCUMENT_ALLOCATOR); + xmlDocument.defineAnnotatedMethods(XmlDocument.class); + + //RubyModule htmlDoc = html.defineOrGetClassUnder("Document", document); + RubyModule htmlDocument = htmlModule.defineClassUnder("Document", xmlDocument, HTML_DOCUMENT_ALLOCATOR); + htmlDocument.defineAnnotatedMethods(HtmlDocument.class); + } + + private void createSaxModule(Ruby ruby, RubyModule xmlSaxModule, RubyModule htmlSaxModule) { + RubyClass xmlSaxParserContext = xmlSaxModule.defineClassUnder("ParserContext", ruby.getObject(), XML_SAXPARSER_CONTEXT_ALLOCATOR); + xmlSaxParserContext.defineAnnotatedMethods(XmlSaxParserContext.class); + + RubyClass xmlSaxPushParser = xmlSaxModule.defineClassUnder("PushParser", ruby.getObject(), XML_SAXPUSHPARSER_ALLOCATOR); + xmlSaxPushParser.defineAnnotatedMethods(XmlSaxPushParser.class); + + RubyClass htmlSaxParserContext = htmlSaxModule.defineClassUnder("ParserContext", xmlSaxParserContext, HTML_SAXPARSER_CONTEXT_ALLOCATOR); + htmlSaxParserContext.defineAnnotatedMethods(HtmlSaxParserContext.class); + } + + private void createXsltModule(Ruby ruby, RubyModule xsltModule) { + RubyClass stylesheet = xsltModule.defineClassUnder("Stylesheet", ruby.getObject(), XSLT_STYLESHEET_ALLOCATOR); + stylesheet.defineAnnotatedMethods(XsltStylesheet.class); + xsltModule.defineAnnotatedMethod(XsltStylesheet.class, "register"); + } + + private static ObjectAllocator ENCODING_HANDLER_ALLOCATOR = new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + return new EncodingHandler(runtime, klazz, ""); + } + }; + + public static final ObjectAllocator HTML_DOCUMENT_ALLOCATOR = new ObjectAllocator() { + private HtmlDocument htmlDocument = null; + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + if (htmlDocument == null) htmlDocument = new HtmlDocument(runtime, klazz); + try { + HtmlDocument clone = (HtmlDocument) htmlDocument.clone(); + clone.setMetaClass(klazz); + return clone; + } catch (CloneNotSupportedException e) { + return new HtmlDocument(runtime, klazz); + } + } + }; + + public static final ObjectAllocator HTML_SAXPARSER_CONTEXT_ALLOCATOR = new ObjectAllocator() { + private HtmlSaxParserContext htmlSaxParserContext = null; + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + if (htmlSaxParserContext == null) htmlSaxParserContext = new HtmlSaxParserContext(runtime, klazz); + try { + HtmlSaxParserContext clone = (HtmlSaxParserContext) htmlSaxParserContext.clone(); + clone.setMetaClass(klazz); + return clone; + } catch (CloneNotSupportedException e) { + return new HtmlSaxParserContext(runtime, klazz); + } + } + }; + + private static ObjectAllocator HTML_ELEMENT_DESCRIPTION_ALLOCATOR = + new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + return new HtmlElementDescription(runtime, klazz); + } + }; + + private static ObjectAllocator HTML_ENTITY_LOOKUP_ALLOCATOR = + new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + return new HtmlEntityLookup(runtime, klazz); + } + }; + + public static final ObjectAllocator XML_ATTR_ALLOCATOR = new ObjectAllocator() { + private XmlAttr xmlAttr = null; + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + if (xmlAttr == null) xmlAttr = new XmlAttr(runtime, klazz); + try { + XmlAttr clone = (XmlAttr) xmlAttr.clone(); + clone.setMetaClass(klazz); + return clone; + } catch (CloneNotSupportedException e) { + return new XmlAttr(runtime, klazz); + } + } + }; + + public static final ObjectAllocator XML_CDATA_ALLOCATOR = new ObjectAllocator() { + private XmlCdata xmlCdata = null; + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + if (xmlCdata == null) xmlCdata = new XmlCdata(runtime, klazz); + try { + XmlCdata clone = (XmlCdata) xmlCdata.clone(); + clone.setMetaClass(klazz); + return clone; + } catch (CloneNotSupportedException e) { + return new XmlCdata(runtime, klazz); + } + } + }; + + public static final ObjectAllocator XML_COMMENT_ALLOCATOR = new ObjectAllocator() { + private XmlComment xmlComment = null; + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + if (xmlComment == null) xmlComment = new XmlComment(runtime, klazz); + try { + XmlComment clone = (XmlComment) xmlComment.clone(); + clone.setMetaClass(klazz); + return clone; + } catch (CloneNotSupportedException e) { + return new XmlComment(runtime, klazz); + } + } + }; + + public static final ObjectAllocator XML_DOCUMENT_ALLOCATOR = new ObjectAllocator() { + private XmlDocument xmlDocument = null; + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + if (xmlDocument == null) xmlDocument = new XmlDocument(runtime, klazz); + try { + XmlDocument clone = (XmlDocument) xmlDocument.clone(); + clone.setMetaClass(klazz); + return clone; + } catch (CloneNotSupportedException e) { + return new XmlDocument(runtime, klazz); + } + } + }; + + public static final ObjectAllocator XML_DOCUMENT_FRAGMENT_ALLOCATOR = new ObjectAllocator() { + private XmlDocumentFragment xmlDocumentFragment = null; + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + if (xmlDocumentFragment == null) xmlDocumentFragment = new XmlDocumentFragment(runtime, klazz); + try { + XmlDocumentFragment clone = (XmlDocumentFragment)xmlDocumentFragment.clone(); + clone.setMetaClass(klazz); + return clone; + } catch (CloneNotSupportedException e) { + return new XmlDocumentFragment(runtime, klazz); + } + } + }; + + public static final ObjectAllocator XML_DTD_ALLOCATOR = new ObjectAllocator() { + private XmlDtd xmlDtd = null; + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + if (xmlDtd == null) xmlDtd = new XmlDtd(runtime, klazz); + try { + XmlDtd clone = (XmlDtd)xmlDtd.clone(); + clone.setMetaClass(klazz); + return clone; + } catch (CloneNotSupportedException e) { + return new XmlDtd(runtime, klazz); + } + } + }; + + public static final ObjectAllocator XML_ELEMENT_ALLOCATOR = new ObjectAllocator() { + private XmlElement xmlElement = null; + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + if (xmlElement == null) xmlElement = new XmlElement(runtime, klazz); + try { + XmlElement clone = (XmlElement)xmlElement.clone(); + clone.setMetaClass(klazz); + return clone; + } catch (CloneNotSupportedException e) { + return new XmlElement(runtime, klazz); + } + } + }; + + public static ObjectAllocator XML_ELEMENT_DECL_ALLOCATOR = new ObjectAllocator() { + private XmlElementDecl xmlElementDecl = null; + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + if (xmlElementDecl == null) xmlElementDecl = new XmlElementDecl(runtime, klazz); + try { + XmlElementDecl clone = (XmlElementDecl)xmlElementDecl.clone(); + clone.setMetaClass(klazz); + return clone; + } catch (CloneNotSupportedException e) { + return new XmlElementDecl(runtime, klazz); + } + } + }; + + public static ObjectAllocator XML_ENTITY_REFERENCE_ALLOCATOR = new ObjectAllocator() { + private XmlEntityReference xmlEntityRef = null; + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + if (xmlEntityRef == null) xmlEntityRef = new XmlEntityReference(runtime, klazz); + try { + XmlEntityReference clone = (XmlEntityReference)xmlEntityRef.clone(); + clone.setMetaClass(klazz); + return clone; + } catch (CloneNotSupportedException e) { + return new XmlEntityReference(runtime, klazz); + } + } + }; + + public static final ObjectAllocator XML_NAMESPACE_ALLOCATOR = new ObjectAllocator() { + private XmlNamespace xmlNamespace = null; + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + if (xmlNamespace == null) xmlNamespace = new XmlNamespace(runtime, klazz); + try { + XmlNamespace clone = (XmlNamespace) xmlNamespace.clone(); + clone.setMetaClass(klazz); + return clone; + } catch (CloneNotSupportedException e) { + return new XmlNamespace(runtime, klazz); + } + } + }; + + public static final ObjectAllocator XML_NODE_ALLOCATOR = new ObjectAllocator() { + private XmlNode xmlNode = null; + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + if (xmlNode == null) xmlNode = new XmlNode(runtime, klazz); + try { + XmlNode clone = (XmlNode) xmlNode.clone(); + clone.setMetaClass(klazz); + return clone; + } catch (CloneNotSupportedException e) { + return new XmlNode(runtime, klazz); + } + } + }; + + public static final ObjectAllocator XML_NODESET_ALLOCATOR = new ObjectAllocator() { + private XmlNodeSet xmlNodeSet = null; + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + if (xmlNodeSet == null) xmlNodeSet = new XmlNodeSet(runtime, klazz); + try { + XmlNodeSet clone = (XmlNodeSet) xmlNodeSet.clone(); + clone.setMetaClass(klazz); + return clone; + } catch (CloneNotSupportedException e) { + xmlNodeSet = new XmlNodeSet(runtime, klazz); + xmlNodeSet.setNodes(RubyArray.newEmptyArray(runtime)); + return xmlNodeSet; + } + } + }; + + public static ObjectAllocator XML_PROCESSING_INSTRUCTION_ALLOCATOR = new ObjectAllocator() { + private XmlProcessingInstruction xmlProcessingInstruction = null; + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + if (xmlProcessingInstruction == null) xmlProcessingInstruction = new XmlProcessingInstruction(runtime, klazz); + try { + XmlProcessingInstruction clone = (XmlProcessingInstruction)xmlProcessingInstruction.clone(); + clone.setMetaClass(klazz); + return clone; + } catch (CloneNotSupportedException e) { + return new XmlProcessingInstruction(runtime, klazz); + } + } + }; + + public static ObjectAllocator XML_READER_ALLOCATOR = new ObjectAllocator() { + private XmlReader xmlReader = null; + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + if (xmlReader == null) xmlReader = new XmlReader(runtime, klazz); + try { + XmlReader clone = (XmlReader) xmlReader.clone(); + clone.setMetaClass(klazz); + return clone; + } catch (CloneNotSupportedException e) { + xmlReader = new XmlReader(runtime, klazz); + return xmlReader; + } + } + }; + + private static ObjectAllocator XML_ATTRIBUTE_DECL_ALLOCATOR = new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + return new XmlAttributeDecl(runtime, klazz); + } + }; + + private static ObjectAllocator XML_ENTITY_DECL_ALLOCATOR = new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + return new XmlEntityDecl(runtime, klazz); + } + }; + + private static ObjectAllocator XML_ELEMENT_CONTENT_ALLOCATOR = new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + throw runtime.newNotImplementedError("not implemented"); + } + }; + + public static final ObjectAllocator XML_RELAXNG_ALLOCATOR = new ObjectAllocator() { + private XmlRelaxng xmlRelaxng = null; + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + if (xmlRelaxng == null) xmlRelaxng = new XmlRelaxng(runtime, klazz); + try { + XmlRelaxng clone = (XmlRelaxng) xmlRelaxng.clone(); + clone.setMetaClass(klazz); + return clone; + } catch (CloneNotSupportedException e) { + return new XmlRelaxng(runtime, klazz); + } + } + }; + + public static final ObjectAllocator XML_SAXPARSER_CONTEXT_ALLOCATOR = new ObjectAllocator() { + private XmlSaxParserContext xmlSaxParserContext = null; + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + if (xmlSaxParserContext == null) xmlSaxParserContext = new XmlSaxParserContext(runtime, klazz); + try { + XmlSaxParserContext clone = (XmlSaxParserContext) xmlSaxParserContext.clone(); + clone.setMetaClass(klazz); + return clone; + } catch (CloneNotSupportedException e) { + return new XmlSaxParserContext(runtime, klazz); + } + } + }; + + private static ObjectAllocator XML_SAXPUSHPARSER_ALLOCATOR = new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + return new XmlSaxPushParser(runtime, klazz); + } + }; + + public static final ObjectAllocator XML_SCHEMA_ALLOCATOR = new ObjectAllocator() { + private XmlSchema xmlSchema = null; + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + if (xmlSchema == null) xmlSchema = new XmlSchema(runtime, klazz); + try { + XmlSchema clone = (XmlSchema) xmlSchema.clone(); + clone.setMetaClass(klazz); + return clone; + } catch (CloneNotSupportedException e) { + return new XmlSchema(runtime, klazz); + } + } + }; + + public static final ObjectAllocator XML_SYNTAXERROR_ALLOCATOR = new ObjectAllocator() { + private XmlSyntaxError xmlSyntaxError = null; + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + if (xmlSyntaxError == null) xmlSyntaxError = new XmlSyntaxError(runtime, klazz); + try { + XmlSyntaxError clone = (XmlSyntaxError) xmlSyntaxError.clone(); + clone.setMetaClass(klazz); + return clone; + } catch (CloneNotSupportedException e) { + return new XmlSyntaxError(runtime, klazz); + } + } + }; + + public static final ObjectAllocator XML_TEXT_ALLOCATOR = new ObjectAllocator() { + private XmlText xmlText = null; + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + if (xmlText == null) xmlText = new XmlText(runtime, klazz); + try { + XmlText clone = (XmlText) xmlText.clone(); + clone.setMetaClass(klazz); + return clone; + } catch (CloneNotSupportedException e) { + return new XmlText(runtime, klazz); + } + } + }; + + public static ObjectAllocator XML_XPATHCONTEXT_ALLOCATOR = new ObjectAllocator() { + private XmlXpathContext xmlXpathContext = null; + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + if (xmlXpathContext == null) xmlXpathContext = new XmlXpathContext(runtime, klazz); + try { + XmlXpathContext clone = (XmlXpathContext) xmlXpathContext.clone(); + clone.setMetaClass(klazz); + return clone; + } catch (CloneNotSupportedException e) { + return new XmlXpathContext(runtime, klazz); + } + } + }; + + public static ObjectAllocator XSLT_STYLESHEET_ALLOCATOR = new ObjectAllocator() { + private XsltStylesheet xsltStylesheet = null; + public IRubyObject allocate(Ruby runtime, RubyClass klazz) { + if (xsltStylesheet == null) xsltStylesheet = new XsltStylesheet(runtime, klazz); + try { + XsltStylesheet clone = (XsltStylesheet) xsltStylesheet.clone(); + clone.setMetaClass(klazz); + return clone; + } catch (CloneNotSupportedException e) { + return new XmlText(runtime, klazz); + } + } + }; +} diff --git a/samples/Java/clojure-type.java b/samples/Java/clojure-type.java new file mode 100644 index 0000000..4cde14a --- /dev/null +++ b/samples/Java/clojure-type.java @@ -0,0 +1,872 @@ +/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package clojure.asm;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+/**
+ * A Java type. This class can be used to make it easier to manipulate type and
+ * method descriptors.
+ *
+ * @author Eric Bruneton
+ * @author Chris Nokleberg
+ */
+public class Type{
+
+/**
+ * The sort of the <tt>void</tt> type. See {@link #getSort getSort}.
+ */
+public final static int VOID = 0;
+
+/**
+ * The sort of the <tt>boolean</tt> type. See {@link #getSort getSort}.
+ */
+public final static int BOOLEAN = 1;
+
+/**
+ * The sort of the <tt>char</tt> type. See {@link #getSort getSort}.
+ */
+public final static int CHAR = 2;
+
+/**
+ * The sort of the <tt>byte</tt> type. See {@link #getSort getSort}.
+ */
+public final static int BYTE = 3;
+
+/**
+ * The sort of the <tt>short</tt> type. See {@link #getSort getSort}.
+ */
+public final static int SHORT = 4;
+
+/**
+ * The sort of the <tt>int</tt> type. See {@link #getSort getSort}.
+ */
+public final static int INT = 5;
+
+/**
+ * The sort of the <tt>float</tt> type. See {@link #getSort getSort}.
+ */
+public final static int FLOAT = 6;
+
+/**
+ * The sort of the <tt>long</tt> type. See {@link #getSort getSort}.
+ */
+public final static int LONG = 7;
+
+/**
+ * The sort of the <tt>double</tt> type. See {@link #getSort getSort}.
+ */
+public final static int DOUBLE = 8;
+
+/**
+ * The sort of array reference types. See {@link #getSort getSort}.
+ */
+public final static int ARRAY = 9;
+
+/**
+ * The sort of object reference type. See {@link #getSort getSort}.
+ */
+public final static int OBJECT = 10;
+
+/**
+ * The <tt>void</tt> type.
+ */
+public final static Type VOID_TYPE = new Type(VOID);
+
+/**
+ * The <tt>boolean</tt> type.
+ */
+public final static Type BOOLEAN_TYPE = new Type(BOOLEAN);
+
+/**
+ * The <tt>char</tt> type.
+ */
+public final static Type CHAR_TYPE = new Type(CHAR);
+
+/**
+ * The <tt>byte</tt> type.
+ */
+public final static Type BYTE_TYPE = new Type(BYTE);
+
+/**
+ * The <tt>short</tt> type.
+ */
+public final static Type SHORT_TYPE = new Type(SHORT);
+
+/**
+ * The <tt>int</tt> type.
+ */
+public final static Type INT_TYPE = new Type(INT);
+
+/**
+ * The <tt>float</tt> type.
+ */
+public final static Type FLOAT_TYPE = new Type(FLOAT);
+
+/**
+ * The <tt>long</tt> type.
+ */
+public final static Type LONG_TYPE = new Type(LONG);
+
+/**
+ * The <tt>double</tt> type.
+ */
+public final static Type DOUBLE_TYPE = new Type(DOUBLE);
+
+// ------------------------------------------------------------------------
+// Fields
+// ------------------------------------------------------------------------
+
+/**
+ * The sort of this Java type.
+ */
+private final int sort;
+
+/**
+ * A buffer containing the descriptor of this Java type. This field is only
+ * used for reference types.
+ */
+private char[] buf;
+
+/**
+ * The offset of the descriptor of this Java type in {@link #buf buf}. This
+ * field is only used for reference types.
+ */
+private int off;
+
+/**
+ * The length of the descriptor of this Java type.
+ */
+private int len;
+
+// ------------------------------------------------------------------------
+// Constructors
+// ------------------------------------------------------------------------
+
+/**
+ * Constructs a primitive type.
+ *
+ * @param sort the sort of the primitive type to be constructed.
+ */
+private Type(final int sort){
+ this.sort = sort;
+ this.len = 1;
+}
+
+/**
+ * Constructs a reference type.
+ *
+ * @param sort the sort of the reference type to be constructed.
+ * @param buf a buffer containing the descriptor of the previous type.
+ * @param off the offset of this descriptor in the previous buffer.
+ * @param len the length of this descriptor.
+ */
+private Type(final int sort, final char[] buf, final int off, final int len){
+ this.sort = sort;
+ this.buf = buf;
+ this.off = off;
+ this.len = len;
+}
+
+/**
+ * Returns the Java type corresponding to the given type descriptor.
+ *
+ * @param typeDescriptor a type descriptor.
+ * @return the Java type corresponding to the given type descriptor.
+ */
+public static Type getType(final String typeDescriptor){
+ return getType(typeDescriptor.toCharArray(), 0);
+}
+
+/**
+ * Returns the Java type corresponding to the given class.
+ *
+ * @param c a class.
+ * @return the Java type corresponding to the given class.
+ */
+public static Type getType(final Class c){
+ if(c.isPrimitive())
+ {
+ if(c == Integer.TYPE)
+ {
+ return INT_TYPE;
+ }
+ else if(c == Void.TYPE)
+ {
+ return VOID_TYPE;
+ }
+ else if(c == Boolean.TYPE)
+ {
+ return BOOLEAN_TYPE;
+ }
+ else if(c == Byte.TYPE)
+ {
+ return BYTE_TYPE;
+ }
+ else if(c == Character.TYPE)
+ {
+ return CHAR_TYPE;
+ }
+ else if(c == Short.TYPE)
+ {
+ return SHORT_TYPE;
+ }
+ else if(c == Double.TYPE)
+ {
+ return DOUBLE_TYPE;
+ }
+ else if(c == Float.TYPE)
+ {
+ return FLOAT_TYPE;
+ }
+ else /* if (c == Long.TYPE) */
+ {
+ return LONG_TYPE;
+ }
+ }
+ else
+ {
+ return getType(getDescriptor(c));
+ }
+}
+
+/**
+ * Returns the {@link Type#OBJECT} type for the given internal class name.
+ * This is a shortcut method for <code>Type.getType("L"+name+";")</code>.
+ * <i>Note that opposed to {@link Type#getType(String)}, this method takes
+ * internal class names and not class descriptor.</i>
+ *
+ * @param name an internal class name.
+ * @return the the {@link Type#OBJECT} type for the given class name.
+ */
+public static Type getObjectType(String name){
+ int l = name.length();
+ char[] buf = new char[l + 2];
+ buf[0] = 'L';
+ buf[l + 1] = ';';
+ name.getChars(0, l, buf, 1);
+ return new Type(OBJECT, buf, 0, l + 2);
+}
+
+/**
+ * Returns the Java types corresponding to the argument types of the given
+ * method descriptor.
+ *
+ * @param methodDescriptor a method descriptor.
+ * @return the Java types corresponding to the argument types of the given
+ * method descriptor.
+ */
+public static Type[] getArgumentTypes(final String methodDescriptor){
+ char[] buf = methodDescriptor.toCharArray();
+ int off = 1;
+ int size = 0;
+ while(true)
+ {
+ char car = buf[off++];
+ if(car == ')')
+ {
+ break;
+ }
+ else if(car == 'L')
+ {
+ while(buf[off++] != ';')
+ {
+ }
+ ++size;
+ }
+ else if(car != '[')
+ {
+ ++size;
+ }
+ }
+ Type[] args = new Type[size];
+ off = 1;
+ size = 0;
+ while(buf[off] != ')')
+ {
+ args[size] = getType(buf, off);
+ off += args[size].len;
+ size += 1;
+ }
+ return args;
+}
+
+/**
+ * Returns the Java types corresponding to the argument types of the given
+ * method.
+ *
+ * @param method a method.
+ * @return the Java types corresponding to the argument types of the given
+ * method.
+ */
+public static Type[] getArgumentTypes(final Method method){
+ Class[] classes = method.getParameterTypes();
+ Type[] types = new Type[classes.length];
+ for(int i = classes.length - 1; i >= 0; --i)
+ {
+ types[i] = getType(classes[i]);
+ }
+ return types;
+}
+
+/**
+ * Returns the Java type corresponding to the return type of the given
+ * method descriptor.
+ *
+ * @param methodDescriptor a method descriptor.
+ * @return the Java type corresponding to the return type of the given
+ * method descriptor.
+ */
+public static Type getReturnType(final String methodDescriptor){
+ char[] buf = methodDescriptor.toCharArray();
+ return getType(buf, methodDescriptor.indexOf(')') + 1);
+}
+
+/**
+ * Returns the Java type corresponding to the return type of the given
+ * method.
+ *
+ * @param method a method.
+ * @return the Java type corresponding to the return type of the given
+ * method.
+ */
+public static Type getReturnType(final Method method){
+ return getType(method.getReturnType());
+}
+
+/**
+ * Returns the Java type corresponding to the given type descriptor.
+ *
+ * @param buf a buffer containing a type descriptor.
+ * @param off the offset of this descriptor in the previous buffer.
+ * @return the Java type corresponding to the given type descriptor.
+ */
+private static Type getType(final char[] buf, final int off){
+ int len;
+ switch(buf[off])
+ {
+ case'V':
+ return VOID_TYPE;
+ case'Z':
+ return BOOLEAN_TYPE;
+ case'C':
+ return CHAR_TYPE;
+ case'B':
+ return BYTE_TYPE;
+ case'S':
+ return SHORT_TYPE;
+ case'I':
+ return INT_TYPE;
+ case'F':
+ return FLOAT_TYPE;
+ case'J':
+ return LONG_TYPE;
+ case'D':
+ return DOUBLE_TYPE;
+ case'[':
+ len = 1;
+ while(buf[off + len] == '[')
+ {
+ ++len;
+ }
+ if(buf[off + len] == 'L')
+ {
+ ++len;
+ while(buf[off + len] != ';')
+ {
+ ++len;
+ }
+ }
+ return new Type(ARRAY, buf, off, len + 1);
+ // case 'L':
+ default:
+ len = 1;
+ while(buf[off + len] != ';')
+ {
+ ++len;
+ }
+ return new Type(OBJECT, buf, off, len + 1);
+ }
+}
+
+// ------------------------------------------------------------------------
+// Accessors
+// ------------------------------------------------------------------------
+
+/**
+ * Returns the sort of this Java type.
+ *
+ * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN},
+ * {@link #CHAR CHAR}, {@link #BYTE BYTE}, {@link #SHORT SHORT},
+ * {@link #INT INT}, {@link #FLOAT FLOAT}, {@link #LONG LONG},
+ * {@link #DOUBLE DOUBLE}, {@link #ARRAY ARRAY} or
+ * {@link #OBJECT OBJECT}.
+ */
+public int getSort(){
+ return sort;
+}
+
+/**
+ * Returns the number of dimensions of this array type. This method should
+ * only be used for an array type.
+ *
+ * @return the number of dimensions of this array type.
+ */
+public int getDimensions(){
+ int i = 1;
+ while(buf[off + i] == '[')
+ {
+ ++i;
+ }
+ return i;
+}
+
+/**
+ * Returns the type of the elements of this array type. This method should
+ * only be used for an array type.
+ *
+ * @return Returns the type of the elements of this array type.
+ */
+public Type getElementType(){
+ return getType(buf, off + getDimensions());
+}
+
+/**
+ * Returns the name of the class corresponding to this type.
+ *
+ * @return the fully qualified name of the class corresponding to this type.
+ */
+public String getClassName(){
+ switch(sort)
+ {
+ case VOID:
+ return "void";
+ case BOOLEAN:
+ return "boolean";
+ case CHAR:
+ return "char";
+ case BYTE:
+ return "byte";
+ case SHORT:
+ return "short";
+ case INT:
+ return "int";
+ case FLOAT:
+ return "float";
+ case LONG:
+ return "long";
+ case DOUBLE:
+ return "double";
+ case ARRAY:
+ StringBuffer b = new StringBuffer(getElementType().getClassName());
+ for(int i = getDimensions(); i > 0; --i)
+ {
+ b.append("[]");
+ }
+ return b.toString();
+ // case OBJECT:
+ default:
+ return new String(buf, off + 1, len - 2).replace('/', '.');
+ }
+}
+
+/**
+ * Returns the internal name of the class corresponding to this object type.
+ * The internal name of a class is its fully qualified name, where '.' are
+ * replaced by '/'. This method should only be used for an object type.
+ *
+ * @return the internal name of the class corresponding to this object type.
+ */
+public String getInternalName(){
+ return new String(buf, off + 1, len - 2);
+}
+
+// ------------------------------------------------------------------------
+// Conversion to type descriptors
+// ------------------------------------------------------------------------
+
+/**
+ * Returns the descriptor corresponding to this Java type.
+ *
+ * @return the descriptor corresponding to this Java type.
+ */
+public String getDescriptor(){
+ StringBuffer buf = new StringBuffer();
+ getDescriptor(buf);
+ return buf.toString();
+}
+
+/**
+ * Returns the descriptor corresponding to the given argument and return
+ * types.
+ *
+ * @param returnType the return type of the method.
+ * @param argumentTypes the argument types of the method.
+ * @return the descriptor corresponding to the given argument and return
+ * types.
+ */
+public static String getMethodDescriptor(
+ final Type returnType,
+ final Type[] argumentTypes){
+ StringBuffer buf = new StringBuffer();
+ buf.append('(');
+ for(int i = 0; i < argumentTypes.length; ++i)
+ {
+ argumentTypes[i].getDescriptor(buf);
+ }
+ buf.append(')');
+ returnType.getDescriptor(buf);
+ return buf.toString();
+}
+
+/**
+ * Appends the descriptor corresponding to this Java type to the given
+ * string buffer.
+ *
+ * @param buf the string buffer to which the descriptor must be appended.
+ */
+private void getDescriptor(final StringBuffer buf){
+ switch(sort)
+ {
+ case VOID:
+ buf.append('V');
+ return;
+ case BOOLEAN:
+ buf.append('Z');
+ return;
+ case CHAR:
+ buf.append('C');
+ return;
+ case BYTE:
+ buf.append('B');
+ return;
+ case SHORT:
+ buf.append('S');
+ return;
+ case INT:
+ buf.append('I');
+ return;
+ case FLOAT:
+ buf.append('F');
+ return;
+ case LONG:
+ buf.append('J');
+ return;
+ case DOUBLE:
+ buf.append('D');
+ return;
+ // case ARRAY:
+ // case OBJECT:
+ default:
+ buf.append(this.buf, off, len);
+ }
+}
+
+// ------------------------------------------------------------------------
+// Direct conversion from classes to type descriptors,
+// without intermediate Type objects
+// ------------------------------------------------------------------------
+
+/**
+ * Returns the internal name of the given class. The internal name of a
+ * class is its fully qualified name, where '.' are replaced by '/'.
+ *
+ * @param c an object class.
+ * @return the internal name of the given class.
+ */
+public static String getInternalName(final Class c){
+ return c.getName().replace('.', '/');
+}
+
+/**
+ * Returns the descriptor corresponding to the given Java type.
+ *
+ * @param c an object class, a primitive class or an array class.
+ * @return the descriptor corresponding to the given class.
+ */
+public static String getDescriptor(final Class c){
+ StringBuffer buf = new StringBuffer();
+ getDescriptor(buf, c);
+ return buf.toString();
+}
+
+/**
+ * Returns the descriptor corresponding to the given constructor.
+ *
+ * @param c a {@link Constructor Constructor} object.
+ * @return the descriptor of the given constructor.
+ */
+public static String getConstructorDescriptor(final Constructor c){
+ Class[] parameters = c.getParameterTypes();
+ StringBuffer buf = new StringBuffer();
+ buf.append('(');
+ for(int i = 0; i < parameters.length; ++i)
+ {
+ getDescriptor(buf, parameters[i]);
+ }
+ return buf.append(")V").toString();
+}
+
+/**
+ * Returns the descriptor corresponding to the given method.
+ *
+ * @param m a {@link Method Method} object.
+ * @return the descriptor of the given method.
+ */
+public static String getMethodDescriptor(final Method m){
+ Class[] parameters = m.getParameterTypes();
+ StringBuffer buf = new StringBuffer();
+ buf.append('(');
+ for(int i = 0; i < parameters.length; ++i)
+ {
+ getDescriptor(buf, parameters[i]);
+ }
+ buf.append(')');
+ getDescriptor(buf, m.getReturnType());
+ return buf.toString();
+}
+
+/**
+ * Appends the descriptor of the given class to the given string buffer.
+ *
+ * @param buf the string buffer to which the descriptor must be appended.
+ * @param c the class whose descriptor must be computed.
+ */
+private static void getDescriptor(final StringBuffer buf, final Class c){
+ Class d = c;
+ while(true)
+ {
+ if(d.isPrimitive())
+ {
+ char car;
+ if(d == Integer.TYPE)
+ {
+ car = 'I';
+ }
+ else if(d == Void.TYPE)
+ {
+ car = 'V';
+ }
+ else if(d == Boolean.TYPE)
+ {
+ car = 'Z';
+ }
+ else if(d == Byte.TYPE)
+ {
+ car = 'B';
+ }
+ else if(d == Character.TYPE)
+ {
+ car = 'C';
+ }
+ else if(d == Short.TYPE)
+ {
+ car = 'S';
+ }
+ else if(d == Double.TYPE)
+ {
+ car = 'D';
+ }
+ else if(d == Float.TYPE)
+ {
+ car = 'F';
+ }
+ else /* if (d == Long.TYPE) */
+ {
+ car = 'J';
+ }
+ buf.append(car);
+ return;
+ }
+ else if(d.isArray())
+ {
+ buf.append('[');
+ d = d.getComponentType();
+ }
+ else
+ {
+ buf.append('L');
+ String name = d.getName();
+ int len = name.length();
+ for(int i = 0; i < len; ++i)
+ {
+ char car = name.charAt(i);
+ buf.append(car == '.' ? '/' : car);
+ }
+ buf.append(';');
+ return;
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+// Corresponding size and opcodes
+// ------------------------------------------------------------------------
+
+/**
+ * Returns the size of values of this type.
+ *
+ * @return the size of values of this type, i.e., 2 for <tt>long</tt> and
+ * <tt>double</tt>, and 1 otherwise.
+ */
+public int getSize(){
+ return sort == LONG || sort == DOUBLE ? 2 : 1;
+}
+
+/**
+ * Returns a JVM instruction opcode adapted to this Java type.
+ *
+ * @param opcode a JVM instruction opcode. This opcode must be one of ILOAD,
+ * ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG, ISHL,
+ * ISHR, IUSHR, IAND, IOR, IXOR and IRETURN.
+ * @return an opcode that is similar to the given opcode, but adapted to
+ * this Java type. For example, if this type is <tt>float</tt> and
+ * <tt>opcode</tt> is IRETURN, this method returns FRETURN.
+ */
+public int getOpcode(final int opcode){
+ if(opcode == Opcodes.IALOAD || opcode == Opcodes.IASTORE)
+ {
+ switch(sort)
+ {
+ case BOOLEAN:
+ case BYTE:
+ return opcode + 5;
+ case CHAR:
+ return opcode + 6;
+ case SHORT:
+ return opcode + 7;
+ case INT:
+ return opcode;
+ case FLOAT:
+ return opcode + 2;
+ case LONG:
+ return opcode + 1;
+ case DOUBLE:
+ return opcode + 3;
+ // case ARRAY:
+ // case OBJECT:
+ default:
+ return opcode + 4;
+ }
+ }
+ else
+ {
+ switch(sort)
+ {
+ case VOID:
+ return opcode + 5;
+ case BOOLEAN:
+ case CHAR:
+ case BYTE:
+ case SHORT:
+ case INT:
+ return opcode;
+ case FLOAT:
+ return opcode + 2;
+ case LONG:
+ return opcode + 1;
+ case DOUBLE:
+ return opcode + 3;
+ // case ARRAY:
+ // case OBJECT:
+ default:
+ return opcode + 4;
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+// Equals, hashCode and toString
+// ------------------------------------------------------------------------
+
+/**
+ * Tests if the given object is equal to this type.
+ *
+ * @param o the object to be compared to this type.
+ * @return <tt>true</tt> if the given object is equal to this type.
+ */
+public boolean equals(final Object o){
+ if(this == o)
+ {
+ return true;
+ }
+ if(!(o instanceof Type))
+ {
+ return false;
+ }
+ Type t = (Type) o;
+ if(sort != t.sort)
+ {
+ return false;
+ }
+ if(sort == Type.OBJECT || sort == Type.ARRAY)
+ {
+ if(len != t.len)
+ {
+ return false;
+ }
+ for(int i = off, j = t.off, end = i + len; i < end; i++, j++)
+ {
+ if(buf[i] != t.buf[j])
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+/**
+ * Returns a hash code value for this type.
+ *
+ * @return a hash code value for this type.
+ */
+public int hashCode(){
+ int hc = 13 * sort;
+ if(sort == Type.OBJECT || sort == Type.ARRAY)
+ {
+ for(int i = off, end = i + len; i < end; i++)
+ {
+ hc = 17 * (hc + buf[i]);
+ }
+ }
+ return hc;
+}
+
+/**
+ * Returns a string representation of this type.
+ *
+ * @return the descriptor of this type.
+ */
+public String toString(){
+ return getDescriptor();
+}
+}
diff --git a/samples/Java/clojure-util.java b/samples/Java/clojure-util.java new file mode 100644 index 0000000..02b5466 --- /dev/null +++ b/samples/Java/clojure-util.java @@ -0,0 +1,197 @@ +/** + * Copyright (c) Rich Hickey. All rights reserved. + * The use and distribution terms for this software are covered by the + * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) + * which can be found in the file epl-v10.html at the root of this distribution. + * By using this software in any fashion, you are agreeing to be bound by + * the terms of this license. + * You must not remove this notice, or any other, from this software. + **/ + +/* rich Apr 19, 2008 */ + +package clojure.lang; + +import java.lang.ref.Reference; +import java.math.BigInteger; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.lang.ref.SoftReference; +import java.lang.ref.ReferenceQueue; + +public class Util{ +static public boolean equiv(Object k1, Object k2){ + if(k1 == k2) + return true; + if(k1 != null) + { + if(k1 instanceof Number && k2 instanceof Number) + return Numbers.equal((Number)k1, (Number)k2); + else if(k1 instanceof IPersistentCollection || k2 instanceof IPersistentCollection) + return pcequiv(k1,k2); + return k1.equals(k2); + } + return false; +} + +static public boolean equiv(long k1, long k2){ + return k1 == k2; +} + +static public boolean equiv(Object k1, long k2){ + return equiv(k1, (Object)k2); +} + +static public boolean equiv(long k1, Object k2){ + return equiv((Object)k1, k2); +} + +static public boolean equiv(double k1, double k2){ + return k1 == k2; +} + +static public boolean equiv(Object k1, double k2){ + return equiv(k1, (Object)k2); +} + +static public boolean equiv(double k1, Object k2){ + return equiv((Object)k1, k2); +} + +static public boolean equiv(boolean k1, boolean k2){ + return k1 == k2; +} + +static public boolean equiv(Object k1, boolean k2){ + return equiv(k1, (Object)k2); +} + +static public boolean equiv(boolean k1, Object k2){ + return equiv((Object)k1, k2); +} + +static public boolean equiv(char c1, char c2) { + return c1 == c2; +} + +static public boolean pcequiv(Object k1, Object k2){ + if(k1 instanceof IPersistentCollection) + return ((IPersistentCollection)k1).equiv(k2); + return ((IPersistentCollection)k2).equiv(k1); +} + +static public boolean equals(Object k1, Object k2){ + if(k1 == k2) + return true; + return k1 != null && k1.equals(k2); +} + +static public boolean identical(Object k1, Object k2){ + return k1 == k2; +} + +static public Class classOf(Object x){ + if(x != null) + return x.getClass(); + return null; +} + +static public int compare(Object k1, Object k2){ + if(k1 == k2) + return 0; + if(k1 != null) + { + if(k2 == null) + return 1; + if(k1 instanceof Number) + return Numbers.compare((Number) k1, (Number) k2); + return ((Comparable) k1).compareTo(k2); + } + return -1; +} + +static public int hash(Object o){ + if(o == null) + return 0; + return o.hashCode(); +} + +static public int hasheq(Object o){ + if(o == null) + return 0; + if(o instanceof Number) + return Numbers.hasheq((Number)o); + else if(o instanceof IHashEq) + return ((IHashEq)o).hasheq(); + return o.hashCode(); +} + +static public int hashCombine(int seed, int hash){ + //a la boost + seed ^= hash + 0x9e3779b9 + (seed << 6) + (seed >> 2); + return seed; +} + +static public boolean isPrimitive(Class c){ + return c != null && c.isPrimitive() && !(c == Void.TYPE); +} + +static public boolean isInteger(Object x){ + return x instanceof Integer + || x instanceof Long + || x instanceof BigInt + || x instanceof BigInteger; +} + +static public Object ret1(Object ret, Object nil){ + return ret; +} + +static public ISeq ret1(ISeq ret, Object nil){ + return ret; +} + +static public <K,V> void clearCache(ReferenceQueue rq, ConcurrentHashMap<K, Reference<V>> cache){ + //cleanup any dead entries + if(rq.poll() != null) + { + while(rq.poll() != null) + ; + for(Map.Entry<K, Reference<V>> e : cache.entrySet()) + { + Reference<V> val = e.getValue(); + if(val != null && val.get() == null) + cache.remove(e.getKey(), val); + } + } +} + +static public RuntimeException runtimeException(String s){ + return new RuntimeException(s); +} + +static public RuntimeException runtimeException(String s, Throwable e){ + return new RuntimeException(s, e); +} + +/** + * Throw even checked exceptions without being required + * to declare them or catch them. Suggested idiom: + * <p> + * <code>throw sneakyThrow( some exception );</code> + */ +static public RuntimeException sneakyThrow(Throwable t) { + // http://www.mail-archive.com/javaposse@googlegroups.com/msg05984.html + if (t == null) + throw new NullPointerException(); + Util.<RuntimeException>sneakyThrow0(t); + return null; +} + +@SuppressWarnings("unchecked") +static private <T extends Throwable> void sneakyThrow0(Throwable t) throws T { + throw (T) t; +} + +} + |
