summaryrefslogtreecommitdiffstats
path: root/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources
diff options
context:
space:
mode:
Diffstat (limited to 'sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources')
-rw-r--r--sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.ImplementationProviderFactory20
-rw-r--r--sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/atomutil.py120
-rw-r--r--sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/django/__init__.py0
-rw-r--r--sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/django/utils/__init__.py0
-rw-r--r--sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/django/utils/simplejson/__init__.py252
-rw-r--r--sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/django/utils/simplejson/decoder.py273
-rw-r--r--sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/django/utils/simplejson/encoder.py331
-rw-r--r--sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/django/utils/simplejson/jsonfilter.py40
-rw-r--r--sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/django/utils/simplejson/scanner.py63
-rw-r--r--sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/elemutil.py168
-rw-r--r--sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/invoker.py108
-rw-r--r--sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/jsonutil.py142
-rw-r--r--sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/rssutil.py119
-rw-r--r--sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/util.py145
-rw-r--r--sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/xmlutil.py114
15 files changed, 1895 insertions, 0 deletions
diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.ImplementationProviderFactory b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.ImplementationProviderFactory
new file mode 100644
index 0000000000..3c1e6c4406
--- /dev/null
+++ b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.ImplementationProviderFactory
@@ -0,0 +1,20 @@
+# 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.
+
+# Implementation provider for Python components
+org.apache.tuscany.sca.implementation.python.provider.PythonImplementationProviderFactory;model=org.apache.tuscany.sca.implementation.python.PythonImplementation
+
diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/atomutil.py b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/atomutil.py
new file mode 100644
index 0000000000..6c0a7c9a81
--- /dev/null
+++ b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/atomutil.py
@@ -0,0 +1,120 @@
+# 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.
+
+# ATOM data conversion functions
+
+from util import *
+from elemutil import *
+from xmlutil import *
+
+# Convert a list of elements to a list of values representing an ATOM entry
+def entryElementsToValues(e):
+ lt = filter(selector((element, "'title")), e)
+ t = "" if isNil(lt) else elementValue(car(lt))
+ li = filter(selector((element, "'id")), e)
+ i = "" if isNil(li) else elementValue(car(li))
+ lc = filter(selector((element, "'content")), e)
+ return (t, i, elementValue(car(lc)))
+
+# Convert a list of elements to a list of values representing ATOM entries
+def entriesElementsToValues(e):
+ if isNil(e):
+ return e
+ return cons(entryElementsToValues(car(e)), entriesElementsToValues(cdr(e)))
+
+# Convert a list of strings to a list of values representing an ATOM entry
+def readATOMEntry(l):
+ e = readXML(l)
+ if isNil(e):
+ return ()
+ return entryElementsToValues(car(e))
+
+# Convert a list of values representy an ATOM entry to a value
+def entryValue(e):
+ v = elementsToValues((caddr(e),))
+ return cons(car(e), (cadr(e), cdr(car(v))))
+
+# Return true if a list of strings represents an ATOM feed
+def isATOMFeed(l):
+ if isNil(l):
+ return False
+ if car(l)[0:5] != "<?xml":
+ return False
+ return contains(car(l), "<feed")
+
+# Convert a list of strings to a list of values representing an ATOM feed
+def readATOMFeed(l):
+ f = readXML(l)
+ if isNil(f):
+ return ()
+ t = filter(selector((element, "'title")), car(f))
+ i = filter(selector((element, "'id")), car(f))
+ e = filter(selector((element, "'entry")), car(f))
+ if isNil(e):
+ return (elementValue(car(t)), elementValue(car(i)))
+ return cons(elementValue(car(t)), cons(elementValue(car(i)), entriesElementsToValues(e)))
+
+# Convert an ATOM feed containing elements to an ATOM feed containing values
+def feedValuesLoop(e):
+ if (isNil(e)):
+ return e
+ return cons(entryValue(car(e)), feedValuesLoop(cdr(e)))
+
+def feedValues(e):
+ return cons(car(e), cons(cadr(e), feedValuesLoop(cddr(e))))
+
+# Convert a list of values representy an ATOM entry to a list of elements
+def entryElement(l):
+ return (element, "'entry", (attribute, "'xmlns", "http://www.w3.org/2005/Atom"),
+ (element, "'title", (attribute, "'type", "text"), car(l)),
+ (element, "'id", cadr(l)),
+ (element, "'content", (attribute, "'type", ("application/xml" if isList(caddr(l)) else "text")), caddr(l)),
+ (element, "'link", (attribute, "'href", cadr(l))))
+
+# Convert a list of values representing ATOM entries to a list of elements
+def entriesElements(l):
+ if isNil(l):
+ return l
+ return cons(entryElement(car(l)), entriesElements(cdr(l)))
+
+# Convert a list of values representing an ATOM entry to an ATOM entry
+def writeATOMEntry(l):
+ return writeXML((entryElement(l),), True)
+
+# Convert a list of values representing an ATOM feed to an ATOM feed
+def writeATOMFeed(l):
+ f = (element, "'feed", (attribute, "'xmlns", "http://www.w3.org/2005/Atom"),
+ (element, "'title", (attribute, "'type", "text"), car(l)),
+ (element, "'id", cadr(l)))
+ if isNil(cddr(l)):
+ return writeXML((f,), True)
+ fe = append(f, entriesElements(cddr(l)))
+ return writeXML((fe,), True)
+
+# Convert an ATOM entry containing a value to an ATOM entry containing an item element
+def entryValuesToElements(v):
+ return cons(car(v), cons(cadr(v), valuesToElements((cons("'item", caddr(v)),))))
+
+# Convert an ATOM feed containing values to an ATOM feed containing elements
+def feedValuesToElementsLoop(v):
+ if isNil(v):
+ return v
+ return cons(entryValuesToElements(car(v)), feedValuesToElementsLoop(cdr(v)))
+
+def feedValuesToElements(v):
+ return cons(car(v), cons(cadr(v), feedValuesToElementsLoop(cddr(v))))
+
diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/django/__init__.py b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/django/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/django/__init__.py
diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/django/utils/__init__.py b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/django/utils/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/django/utils/__init__.py
diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/django/utils/simplejson/__init__.py b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/django/utils/simplejson/__init__.py
new file mode 100644
index 0000000000..15b7173976
--- /dev/null
+++ b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/django/utils/simplejson/__init__.py
@@ -0,0 +1,252 @@
+r"""
+A simple, fast, extensible JSON encoder and decoder
+
+JSON (JavaScript Object Notation) <http://json.org> is a subset of
+JavaScript syntax (ECMA-262 3rd edition) used as a lightweight data
+interchange format.
+
+simplejson exposes an API familiar to uses of the standard library
+marshal and pickle modules.
+
+Encoding basic Python object hierarchies::
+
+ >>> import simplejson
+ >>> simplejson.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}])
+ '["foo", {"bar": ["baz", null, 1.0, 2]}]'
+ >>> print simplejson.dumps("\"foo\bar")
+ "\"foo\bar"
+ >>> print simplejson.dumps(u'\u1234')
+ "\u1234"
+ >>> print simplejson.dumps('\\')
+ "\\"
+ >>> print simplejson.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True)
+ {"a": 0, "b": 0, "c": 0}
+ >>> from StringIO import StringIO
+ >>> io = StringIO()
+ >>> simplejson.dump(['streaming API'], io)
+ >>> io.getvalue()
+ '["streaming API"]'
+
+Compact encoding::
+
+ >>> import simplejson
+ >>> simplejson.dumps([1,2,3,{'4': 5, '6': 7}], separators=(',',':'))
+ '[1,2,3,{"4":5,"6":7}]'
+
+Pretty printing::
+
+ >>> import simplejson
+ >>> print simplejson.dumps({'4': 5, '6': 7}, sort_keys=True, indent=4)
+ {
+ "4": 5,
+ "6": 7
+ }
+
+Decoding JSON::
+
+ >>> import simplejson
+ >>> simplejson.loads('["foo", {"bar":["baz", null, 1.0, 2]}]')
+ [u'foo', {u'bar': [u'baz', None, 1.0, 2]}]
+ >>> simplejson.loads('"\\"foo\\bar"')
+ u'"foo\x08ar'
+ >>> from StringIO import StringIO
+ >>> io = StringIO('["streaming API"]')
+ >>> simplejson.load(io)
+ [u'streaming API']
+
+Specializing JSON object decoding::
+
+ >>> import simplejson
+ >>> def as_complex(dct):
+ ... if '__complex__' in dct:
+ ... return complex(dct['real'], dct['imag'])
+ ... return dct
+ ...
+ >>> simplejson.loads('{"__complex__": true, "real": 1, "imag": 2}',
+ ... object_hook=as_complex)
+ (1+2j)
+
+Extending JSONEncoder::
+
+ >>> import simplejson
+ >>> class ComplexEncoder(simplejson.JSONEncoder):
+ ... def default(self, obj):
+ ... if isinstance(obj, complex):
+ ... return [obj.real, obj.imag]
+ ... return simplejson.JSONEncoder.default(self, obj)
+ ...
+ >>> dumps(2 + 1j, cls=ComplexEncoder)
+ '[2.0, 1.0]'
+ >>> ComplexEncoder().encode(2 + 1j)
+ '[2.0, 1.0]'
+ >>> list(ComplexEncoder().iterencode(2 + 1j))
+ ['[', '2.0', ', ', '1.0', ']']
+
+
+Note that the JSON produced by this module's default settings
+is a subset of YAML, so it may be used as a serializer for that as well.
+"""
+__version__ = '1.5'
+__all__ = [
+ 'dump', 'dumps', 'load', 'loads',
+ 'JSONDecoder', 'JSONEncoder',
+]
+
+from django.utils.simplejson.decoder import JSONDecoder
+from django.utils.simplejson.encoder import JSONEncoder
+
+def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True,
+ allow_nan=True, cls=None, indent=None, **kw):
+ """
+ Serialize ``obj`` as a JSON formatted stream to ``fp`` (a
+ ``.write()``-supporting file-like object).
+
+ If ``skipkeys`` is ``True`` then ``dict`` keys that are not basic types
+ (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``)
+ will be skipped instead of raising a ``TypeError``.
+
+ If ``ensure_ascii`` is ``False``, then the some chunks written to ``fp``
+ may be ``unicode`` instances, subject to normal Python ``str`` to
+ ``unicode`` coercion rules. Unless ``fp.write()`` explicitly
+ understands ``unicode`` (as in ``codecs.getwriter()``) this is likely
+ to cause an error.
+
+ If ``check_circular`` is ``False``, then the circular reference check
+ for container types will be skipped and a circular reference will
+ result in an ``OverflowError`` (or worse).
+
+ If ``allow_nan`` is ``False``, then it will be a ``ValueError`` to
+ serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``)
+ in strict compliance of the JSON specification, instead of using the
+ JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).
+
+ If ``indent`` is a non-negative integer, then JSON array elements and object
+ members will be pretty-printed with that indent level. An indent level
+ of 0 will only insert newlines. ``None`` is the most compact representation.
+
+ To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
+ ``.default()`` method to serialize additional types), specify it with
+ the ``cls`` kwarg.
+ """
+ if cls is None:
+ cls = JSONEncoder
+ iterable = cls(skipkeys=skipkeys, ensure_ascii=ensure_ascii,
+ check_circular=check_circular, allow_nan=allow_nan, indent=indent,
+ **kw).iterencode(obj)
+ # could accelerate with writelines in some versions of Python, at
+ # a debuggability cost
+ for chunk in iterable:
+ fp.write(chunk)
+
+def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True,
+ allow_nan=True, cls=None, indent=None, separators=None, **kw):
+ """
+ Serialize ``obj`` to a JSON formatted ``str``.
+
+ If ``skipkeys`` is ``True`` then ``dict`` keys that are not basic types
+ (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``)
+ will be skipped instead of raising a ``TypeError``.
+
+ If ``ensure_ascii`` is ``False``, then the return value will be a
+ ``unicode`` instance subject to normal Python ``str`` to ``unicode``
+ coercion rules instead of being escaped to an ASCII ``str``.
+
+ If ``check_circular`` is ``False``, then the circular reference check
+ for container types will be skipped and a circular reference will
+ result in an ``OverflowError`` (or worse).
+
+ If ``allow_nan`` is ``False``, then it will be a ``ValueError`` to
+ serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) in
+ strict compliance of the JSON specification, instead of using the
+ JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).
+
+ If ``indent`` is a non-negative integer, then JSON array elements and
+ object members will be pretty-printed with that indent level. An indent
+ level of 0 will only insert newlines. ``None`` is the most compact
+ representation.
+
+ If ``separators`` is an ``(item_separator, dict_separator)`` tuple
+ then it will be used instead of the default ``(', ', ': ')`` separators.
+ ``(',', ':')`` is the most compact JSON representation.
+
+ To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
+ ``.default()`` method to serialize additional types), specify it with
+ the ``cls`` kwarg.
+ """
+ if cls is None:
+ cls = JSONEncoder
+ return cls(
+ skipkeys=skipkeys, ensure_ascii=ensure_ascii,
+ check_circular=check_circular, allow_nan=allow_nan, indent=indent,
+ separators=separators,
+ **kw).encode(obj)
+
+def load(fp, encoding=None, cls=None, object_hook=None, **kw):
+ """
+ Deserialize ``fp`` (a ``.read()``-supporting file-like object containing
+ a JSON document) to a Python object.
+
+ If the contents of ``fp`` is encoded with an ASCII based encoding other
+ than utf-8 (e.g. latin-1), then an appropriate ``encoding`` name must
+ be specified. Encodings that are not ASCII based (such as UCS-2) are
+ not allowed, and should be wrapped with
+ ``codecs.getreader(fp)(encoding)``, or simply decoded to a ``unicode``
+ object and passed to ``loads()``
+
+ ``object_hook`` is an optional function that will be called with the
+ result of any object literal decode (a ``dict``). The return value of
+ ``object_hook`` will be used instead of the ``dict``. This feature
+ can be used to implement custom decoders (e.g. JSON-RPC class hinting).
+
+ To use a custom ``JSONDecoder`` subclass, specify it with the ``cls``
+ kwarg.
+ """
+ if cls is None:
+ cls = JSONDecoder
+ if object_hook is not None:
+ kw['object_hook'] = object_hook
+ return cls(encoding=encoding, **kw).decode(fp.read())
+
+def loads(s, encoding=None, cls=None, object_hook=None, **kw):
+ """
+ Deserialize ``s`` (a ``str`` or ``unicode`` instance containing a JSON
+ document) to a Python object.
+
+ If ``s`` is a ``str`` instance and is encoded with an ASCII based encoding
+ other than utf-8 (e.g. latin-1) then an appropriate ``encoding`` name
+ must be specified. Encodings that are not ASCII based (such as UCS-2)
+ are not allowed and should be decoded to ``unicode`` first.
+
+ ``object_hook`` is an optional function that will be called with the
+ result of any object literal decode (a ``dict``). The return value of
+ ``object_hook`` will be used instead of the ``dict``. This feature
+ can be used to implement custom decoders (e.g. JSON-RPC class hinting).
+
+ To use a custom ``JSONDecoder`` subclass, specify it with the ``cls``
+ kwarg.
+ """
+ if cls is None:
+ cls = JSONDecoder
+ if object_hook is not None:
+ kw['object_hook'] = object_hook
+ return cls(encoding=encoding, **kw).decode(s)
+
+def read(s):
+ """
+ json-py API compatibility hook. Use loads(s) instead.
+ """
+ import warnings
+ warnings.warn("simplejson.loads(s) should be used instead of read(s)",
+ DeprecationWarning)
+ return loads(s)
+
+def write(obj):
+ """
+ json-py API compatibility hook. Use dumps(s) instead.
+ """
+ import warnings
+ warnings.warn("simplejson.dumps(s) should be used instead of write(s)",
+ DeprecationWarning)
+ return dumps(obj)
+
+
diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/django/utils/simplejson/decoder.py b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/django/utils/simplejson/decoder.py
new file mode 100644
index 0000000000..66f68a200b
--- /dev/null
+++ b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/django/utils/simplejson/decoder.py
@@ -0,0 +1,273 @@
+"""
+Implementation of JSONDecoder
+"""
+import re
+
+from django.utils.simplejson.scanner import Scanner, pattern
+
+FLAGS = re.VERBOSE | re.MULTILINE | re.DOTALL
+
+def _floatconstants():
+ import struct
+ import sys
+ _BYTES = '7FF80000000000007FF0000000000000'.decode('hex')
+ if sys.byteorder != 'big':
+ _BYTES = _BYTES[:8][::-1] + _BYTES[8:][::-1]
+ nan, inf = struct.unpack('dd', _BYTES)
+ return nan, inf, -inf
+
+NaN, PosInf, NegInf = _floatconstants()
+
+def linecol(doc, pos):
+ lineno = doc.count('\n', 0, pos) + 1
+ if lineno == 1:
+ colno = pos
+ else:
+ colno = pos - doc.rindex('\n', 0, pos)
+ return lineno, colno
+
+def errmsg(msg, doc, pos, end=None):
+ lineno, colno = linecol(doc, pos)
+ if end is None:
+ return '%s: line %d column %d (char %d)' % (msg, lineno, colno, pos)
+ endlineno, endcolno = linecol(doc, end)
+ return '%s: line %d column %d - line %d column %d (char %d - %d)' % (
+ msg, lineno, colno, endlineno, endcolno, pos, end)
+
+_CONSTANTS = {
+ '-Infinity': NegInf,
+ 'Infinity': PosInf,
+ 'NaN': NaN,
+ 'true': True,
+ 'false': False,
+ 'null': None,
+}
+
+def JSONConstant(match, context, c=_CONSTANTS):
+ return c[match.group(0)], None
+pattern('(-?Infinity|NaN|true|false|null)')(JSONConstant)
+
+def JSONNumber(match, context):
+ match = JSONNumber.regex.match(match.string, *match.span())
+ integer, frac, exp = match.groups()
+ if frac or exp:
+ res = float(integer + (frac or '') + (exp or ''))
+ else:
+ res = int(integer)
+ return res, None
+pattern(r'(-?(?:0|[1-9]\d*))(\.\d+)?([eE][-+]?\d+)?')(JSONNumber)
+
+STRINGCHUNK = re.compile(r'(.*?)(["\\])', FLAGS)
+BACKSLASH = {
+ '"': u'"', '\\': u'\\', '/': u'/',
+ 'b': u'\b', 'f': u'\f', 'n': u'\n', 'r': u'\r', 't': u'\t',
+}
+
+DEFAULT_ENCODING = "utf-8"
+
+def scanstring(s, end, encoding=None, _b=BACKSLASH, _m=STRINGCHUNK.match):
+ if encoding is None:
+ encoding = DEFAULT_ENCODING
+ chunks = []
+ _append = chunks.append
+ begin = end - 1
+ while 1:
+ chunk = _m(s, end)
+ if chunk is None:
+ raise ValueError(
+ errmsg("Unterminated string starting at", s, begin))
+ end = chunk.end()
+ content, terminator = chunk.groups()
+ if content:
+ if not isinstance(content, unicode):
+ content = unicode(content, encoding)
+ _append(content)
+ if terminator == '"':
+ break
+ try:
+ esc = s[end]
+ except IndexError:
+ raise ValueError(
+ errmsg("Unterminated string starting at", s, begin))
+ if esc != 'u':
+ try:
+ m = _b[esc]
+ except KeyError:
+ raise ValueError(
+ errmsg("Invalid \\escape: %r" % (esc,), s, end))
+ end += 1
+ else:
+ esc = s[end + 1:end + 5]
+ try:
+ m = unichr(int(esc, 16))
+ if len(esc) != 4 or not esc.isalnum():
+ raise ValueError
+ except ValueError:
+ raise ValueError(errmsg("Invalid \\uXXXX escape", s, end))
+ end += 5
+ _append(m)
+ return u''.join(chunks), end
+
+def JSONString(match, context):
+ encoding = getattr(context, 'encoding', None)
+ return scanstring(match.string, match.end(), encoding)
+pattern(r'"')(JSONString)
+
+WHITESPACE = re.compile(r'\s*', FLAGS)
+
+def JSONObject(match, context, _w=WHITESPACE.match):
+ pairs = {}
+ s = match.string
+ end = _w(s, match.end()).end()
+ nextchar = s[end:end + 1]
+ # trivial empty object
+ if nextchar == '}':
+ return pairs, end + 1
+ if nextchar != '"':
+ raise ValueError(errmsg("Expecting property name", s, end))
+ end += 1
+ encoding = getattr(context, 'encoding', None)
+ iterscan = JSONScanner.iterscan
+ while True:
+ key, end = scanstring(s, end, encoding)
+ end = _w(s, end).end()
+ if s[end:end + 1] != ':':
+ raise ValueError(errmsg("Expecting : delimiter", s, end))
+ end = _w(s, end + 1).end()
+ try:
+ value, end = iterscan(s, idx=end, context=context).next()
+ except StopIteration:
+ raise ValueError(errmsg("Expecting object", s, end))
+ pairs[key] = value
+ end = _w(s, end).end()
+ nextchar = s[end:end + 1]
+ end += 1
+ if nextchar == '}':
+ break
+ if nextchar != ',':
+ raise ValueError(errmsg("Expecting , delimiter", s, end - 1))
+ end = _w(s, end).end()
+ nextchar = s[end:end + 1]
+ end += 1
+ if nextchar != '"':
+ raise ValueError(errmsg("Expecting property name", s, end - 1))
+ object_hook = getattr(context, 'object_hook', None)
+ if object_hook is not None:
+ pairs = object_hook(pairs)
+ return pairs, end
+pattern(r'{')(JSONObject)
+
+def JSONArray(match, context, _w=WHITESPACE.match):
+ values = []
+ s = match.string
+ end = _w(s, match.end()).end()
+ # look-ahead for trivial empty array
+ nextchar = s[end:end + 1]
+ if nextchar == ']':
+ return values, end + 1
+ iterscan = JSONScanner.iterscan
+ while True:
+ try:
+ value, end = iterscan(s, idx=end, context=context).next()
+ except StopIteration:
+ raise ValueError(errmsg("Expecting object", s, end))
+ values.append(value)
+ end = _w(s, end).end()
+ nextchar = s[end:end + 1]
+ end += 1
+ if nextchar == ']':
+ break
+ if nextchar != ',':
+ raise ValueError(errmsg("Expecting , delimiter", s, end))
+ end = _w(s, end).end()
+ return values, end
+pattern(r'\[')(JSONArray)
+
+ANYTHING = [
+ JSONObject,
+ JSONArray,
+ JSONString,
+ JSONConstant,
+ JSONNumber,
+]
+
+JSONScanner = Scanner(ANYTHING)
+
+class JSONDecoder(object):
+ """
+ Simple JSON <http://json.org> decoder
+
+ Performs the following translations in decoding:
+
+ +---------------+-------------------+
+ | JSON | Python |
+ +===============+===================+
+ | object | dict |
+ +---------------+-------------------+
+ | array | list |
+ +---------------+-------------------+
+ | string | unicode |
+ +---------------+-------------------+
+ | number (int) | int, long |
+ +---------------+-------------------+
+ | number (real) | float |
+ +---------------+-------------------+
+ | true | True |
+ +---------------+-------------------+
+ | false | False |
+ +---------------+-------------------+
+ | null | None |
+ +---------------+-------------------+
+
+ It also understands ``NaN``, ``Infinity``, and ``-Infinity`` as
+ their corresponding ``float`` values, which is outside the JSON spec.
+ """
+
+ _scanner = Scanner(ANYTHING)
+ __all__ = ['__init__', 'decode', 'raw_decode']
+
+ def __init__(self, encoding=None, object_hook=None):
+ """
+ ``encoding`` determines the encoding used to interpret any ``str``
+ objects decoded by this instance (utf-8 by default). It has no
+ effect when decoding ``unicode`` objects.
+
+ Note that currently only encodings that are a superset of ASCII work,
+ strings of other encodings should be passed in as ``unicode``.
+
+ ``object_hook``, if specified, will be called with the result
+ of every JSON object decoded and its return value will be used in
+ place of the given ``dict``. This can be used to provide custom
+ deserializations (e.g. to support JSON-RPC class hinting).
+ """
+ self.encoding = encoding
+ self.object_hook = object_hook
+
+ def decode(self, s, _w=WHITESPACE.match):
+ """
+ Return the Python representation of ``s`` (a ``str`` or ``unicode``
+ instance containing a JSON document)
+ """
+ obj, end = self.raw_decode(s, idx=_w(s, 0).end())
+ end = _w(s, end).end()
+ if end != len(s):
+ raise ValueError(errmsg("Extra data", s, end, len(s)))
+ return obj
+
+ def raw_decode(self, s, **kw):
+ """
+ Decode a JSON document from ``s`` (a ``str`` or ``unicode`` beginning
+ with a JSON document) and return a 2-tuple of the Python
+ representation and the index in ``s`` where the document ended.
+
+ This can be used to decode a JSON document from a string that may
+ have extraneous data at the end.
+ """
+ kw.setdefault('context', self)
+ try:
+ obj, end = self._scanner.iterscan(s, **kw).next()
+ except StopIteration:
+ raise ValueError("No JSON object could be decoded")
+ return obj, end
+
+__all__ = ['JSONDecoder']
diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/django/utils/simplejson/encoder.py b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/django/utils/simplejson/encoder.py
new file mode 100644
index 0000000000..c83c6873eb
--- /dev/null
+++ b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/django/utils/simplejson/encoder.py
@@ -0,0 +1,331 @@
+"""
+Implementation of JSONEncoder
+"""
+import re
+
+ESCAPE = re.compile(r'[\x00-\x19\\"\b\f\n\r\t]')
+ESCAPE_ASCII = re.compile(r'([\\"/]|[^\ -~])')
+ESCAPE_DCT = {
+ # escape all forward slashes to prevent </script> attack
+ '/': '\\/',
+ '\\': '\\\\',
+ '"': '\\"',
+ '\b': '\\b',
+ '\f': '\\f',
+ '\n': '\\n',
+ '\r': '\\r',
+ '\t': '\\t',
+}
+for i in range(0x20):
+ ESCAPE_DCT.setdefault(chr(i), '\\u%04x' % (i,))
+
+# assume this produces an infinity on all machines (probably not guaranteed)
+INFINITY = float('1e66666')
+
+def floatstr(o, allow_nan=True):
+ # Check for specials. Note that this type of test is processor- and/or
+ # platform-specific, so do tests which don't depend on the internals.
+
+ if o != o:
+ text = 'NaN'
+ elif o == INFINITY:
+ text = 'Infinity'
+ elif o == -INFINITY:
+ text = '-Infinity'
+ else:
+ return str(o)
+
+ if not allow_nan:
+ raise ValueError("Out of range float values are not JSON compliant: %r"
+ % (o,))
+
+ return text
+
+
+def encode_basestring(s):
+ """
+ Return a JSON representation of a Python string
+ """
+ def replace(match):
+ return ESCAPE_DCT[match.group(0)]
+ return '"' + ESCAPE.sub(replace, s) + '"'
+
+def encode_basestring_ascii(s):
+ def replace(match):
+ s = match.group(0)
+ try:
+ return ESCAPE_DCT[s]
+ except KeyError:
+ return '\\u%04x' % (ord(s),)
+ return '"' + str(ESCAPE_ASCII.sub(replace, s)) + '"'
+
+
+class JSONEncoder(object):
+ """
+ Extensible JSON <http://json.org> encoder for Python data structures.
+
+ Supports the following objects and types by default:
+
+ +-------------------+---------------+
+ | Python | JSON |
+ +===================+===============+
+ | dict | object |
+ +-------------------+---------------+
+ | list, tuple | array |
+ +-------------------+---------------+
+ | str, unicode | string |
+ +-------------------+---------------+
+ | int, long, float | number |
+ +-------------------+---------------+
+ | True | true |
+ +-------------------+---------------+
+ | False | false |
+ +-------------------+---------------+
+ | None | null |
+ +-------------------+---------------+
+
+ To extend this to recognize other objects, subclass and implement a
+ ``.default()`` method with another method that returns a serializable
+ object for ``o`` if possible, otherwise it should call the superclass
+ implementation (to raise ``TypeError``).
+ """
+ __all__ = ['__init__', 'default', 'encode', 'iterencode']
+ item_separator = ', '
+ key_separator = ': '
+ def __init__(self, skipkeys=False, ensure_ascii=True,
+ check_circular=True, allow_nan=True, sort_keys=False,
+ indent=None, separators=None):
+ """
+ Constructor for JSONEncoder, with sensible defaults.
+
+ If skipkeys is False, then it is a TypeError to attempt
+ encoding of keys that are not str, int, long, float or None. If
+ skipkeys is True, such items are simply skipped.
+
+ If ensure_ascii is True, the output is guaranteed to be str
+ objects with all incoming unicode characters escaped. If
+ ensure_ascii is false, the output will be unicode object.
+
+ If check_circular is True, then lists, dicts, and custom encoded
+ objects will be checked for circular references during encoding to
+ prevent an infinite recursion (which would cause an OverflowError).
+ Otherwise, no such check takes place.
+
+ If allow_nan is True, then NaN, Infinity, and -Infinity will be
+ encoded as such. This behavior is not JSON specification compliant,
+ but is consistent with most JavaScript based encoders and decoders.
+ Otherwise, it will be a ValueError to encode such floats.
+
+ If sort_keys is True, then the output of dictionaries will be
+ sorted by key; this is useful for regression tests to ensure
+ that JSON serializations can be compared on a day-to-day basis.
+
+ If indent is a non-negative integer, then JSON array
+ elements and object members will be pretty-printed with that
+ indent level. An indent level of 0 will only insert newlines.
+ None is the most compact representation.
+
+ If specified, separators should be a (item_separator, key_separator)
+ tuple. The default is (', ', ': '). To get the most compact JSON
+ representation you should specify (',', ':') to eliminate whitespace.
+ """
+
+ self.skipkeys = skipkeys
+ self.ensure_ascii = ensure_ascii
+ self.check_circular = check_circular
+ self.allow_nan = allow_nan
+ self.sort_keys = sort_keys
+ self.indent = indent
+ self.current_indent_level = 0
+ if separators is not None:
+ self.item_separator, self.key_separator = separators
+
+ def _newline_indent(self):
+ return '\n' + (' ' * (self.indent * self.current_indent_level))
+
+ def _iterencode_list(self, lst, markers=None):
+ if not lst:
+ yield '[]'
+ return
+ if markers is not None:
+ markerid = id(lst)
+ if markerid in markers:
+ raise ValueError("Circular reference detected")
+ markers[markerid] = lst
+ yield '['
+ if self.indent is not None:
+ self.current_indent_level += 1
+ newline_indent = self._newline_indent()
+ separator = self.item_separator + newline_indent
+ yield newline_indent
+ else:
+ newline_indent = None
+ separator = self.item_separator
+ first = True
+ for value in lst:
+ if first:
+ first = False
+ else:
+ yield separator
+ for chunk in self._iterencode(value, markers):
+ yield chunk
+ if newline_indent is not None:
+ self.current_indent_level -= 1
+ yield self._newline_indent()
+ yield ']'
+ if markers is not None:
+ del markers[markerid]
+
+ def _iterencode_dict(self, dct, markers=None):
+ if not dct:
+ yield '{}'
+ return
+ if markers is not None:
+ markerid = id(dct)
+ if markerid in markers:
+ raise ValueError("Circular reference detected")
+ markers[markerid] = dct
+ yield '{'
+ key_separator = self.key_separator
+ if self.indent is not None:
+ self.current_indent_level += 1
+ newline_indent = self._newline_indent()
+ item_separator = self.item_separator + newline_indent
+ yield newline_indent
+ else:
+ newline_indent = None
+ item_separator = self.item_separator
+ first = True
+ if self.ensure_ascii:
+ encoder = encode_basestring_ascii
+ else:
+ encoder = encode_basestring
+ allow_nan = self.allow_nan
+ if self.sort_keys:
+ keys = dct.keys()
+ keys.sort()
+ items = [(k, dct[k]) for k in keys]
+ else:
+ items = dct.iteritems()
+ for key, value in items:
+ if isinstance(key, basestring):
+ pass
+ # JavaScript is weakly typed for these, so it makes sense to
+ # also allow them. Many encoders seem to do something like this.
+ elif isinstance(key, float):
+ key = floatstr(key, allow_nan)
+ elif isinstance(key, (int, long)):
+ key = str(key)
+ elif key is True:
+ key = 'true'
+ elif key is False:
+ key = 'false'
+ elif key is None:
+ key = 'null'
+ elif self.skipkeys:
+ continue
+ else:
+ raise TypeError("key %r is not a string" % (key,))
+ if first:
+ first = False
+ else:
+ yield item_separator
+ yield encoder(key)
+ yield key_separator
+ for chunk in self._iterencode(value, markers):
+ yield chunk
+ if newline_indent is not None:
+ self.current_indent_level -= 1
+ yield self._newline_indent()
+ yield '}'
+ if markers is not None:
+ del markers[markerid]
+
+ def _iterencode(self, o, markers=None):
+ if isinstance(o, basestring):
+ if self.ensure_ascii:
+ encoder = encode_basestring_ascii
+ else:
+ encoder = encode_basestring
+ yield encoder(o)
+ elif o is None:
+ yield 'null'
+ elif o is True:
+ yield 'true'
+ elif o is False:
+ yield 'false'
+ elif isinstance(o, (int, long)):
+ yield str(o)
+ elif isinstance(o, float):
+ yield floatstr(o, self.allow_nan)
+ elif isinstance(o, (list, tuple)):
+ for chunk in self._iterencode_list(o, markers):
+ yield chunk
+ elif isinstance(o, dict):
+ for chunk in self._iterencode_dict(o, markers):
+ yield chunk
+ else:
+ if markers is not None:
+ markerid = id(o)
+ if markerid in markers:
+ raise ValueError("Circular reference detected")
+ markers[markerid] = o
+ for chunk in self._iterencode_default(o, markers):
+ yield chunk
+ if markers is not None:
+ del markers[markerid]
+
+ def _iterencode_default(self, o, markers=None):
+ newobj = self.default(o)
+ return self._iterencode(newobj, markers)
+
+ def default(self, o):
+ """
+ Implement this method in a subclass such that it returns
+ a serializable object for ``o``, or calls the base implementation
+ (to raise a ``TypeError``).
+
+ For example, to support arbitrary iterators, you could
+ implement default like this::
+
+ def default(self, o):
+ try:
+ iterable = iter(o)
+ except TypeError:
+ pass
+ else:
+ return list(iterable)
+ return JSONEncoder.default(self, o)
+ """
+ raise TypeError("%r is not JSON serializable" % (o,))
+
+ def encode(self, o):
+ """
+ Return a JSON string representation of a Python data structure.
+
+ >>> JSONEncoder().encode({"foo": ["bar", "baz"]})
+ '{"foo":["bar", "baz"]}'
+ """
+ # This doesn't pass the iterator directly to ''.join() because it
+ # sucks at reporting exceptions. It's going to do this internally
+ # anyway because it uses PySequence_Fast or similar.
+ chunks = list(self.iterencode(o))
+ return ''.join(chunks)
+
+ def iterencode(self, o):
+ """
+ Encode the given object and yield each string
+ representation as available.
+
+ For example::
+
+ for chunk in JSONEncoder().iterencode(bigobject):
+ mysocket.write(chunk)
+ """
+ if self.check_circular:
+ markers = {}
+ else:
+ markers = None
+ return self._iterencode(o, markers)
+
+__all__ = ['JSONEncoder']
diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/django/utils/simplejson/jsonfilter.py b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/django/utils/simplejson/jsonfilter.py
new file mode 100644
index 0000000000..d02ae2033a
--- /dev/null
+++ b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/django/utils/simplejson/jsonfilter.py
@@ -0,0 +1,40 @@
+from django.utils import simplejson
+import cgi
+
+class JSONFilter(object):
+ def __init__(self, app, mime_type='text/x-json'):
+ self.app = app
+ self.mime_type = mime_type
+
+ def __call__(self, environ, start_response):
+ # Read JSON POST input to jsonfilter.json if matching mime type
+ response = {'status': '200 OK', 'headers': []}
+ def json_start_response(status, headers):
+ response['status'] = status
+ response['headers'].extend(headers)
+ environ['jsonfilter.mime_type'] = self.mime_type
+ if environ.get('REQUEST_METHOD', '') == 'POST':
+ if environ.get('CONTENT_TYPE', '') == self.mime_type:
+ args = [_ for _ in [environ.get('CONTENT_LENGTH')] if _]
+ data = environ['wsgi.input'].read(*map(int, args))
+ environ['jsonfilter.json'] = simplejson.loads(data)
+ res = simplejson.dumps(self.app(environ, json_start_response))
+ jsonp = cgi.parse_qs(environ.get('QUERY_STRING', '')).get('jsonp')
+ if jsonp:
+ content_type = 'text/javascript'
+ res = ''.join(jsonp + ['(', res, ')'])
+ elif 'Opera' in environ.get('HTTP_USER_AGENT', ''):
+ # Opera has bunk XMLHttpRequest support for most mime types
+ content_type = 'text/plain'
+ else:
+ content_type = self.mime_type
+ headers = [
+ ('Content-type', content_type),
+ ('Content-length', len(res)),
+ ]
+ headers.extend(response['headers'])
+ start_response(response['status'], headers)
+ return [res]
+
+def factory(app, global_conf, **kw):
+ return JSONFilter(app, **kw)
diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/django/utils/simplejson/scanner.py b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/django/utils/simplejson/scanner.py
new file mode 100644
index 0000000000..64f4999fb5
--- /dev/null
+++ b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/django/utils/simplejson/scanner.py
@@ -0,0 +1,63 @@
+"""
+Iterator based sre token scanner
+"""
+import sre_parse, sre_compile, sre_constants
+from sre_constants import BRANCH, SUBPATTERN
+from re import VERBOSE, MULTILINE, DOTALL
+import re
+
+__all__ = ['Scanner', 'pattern']
+
+FLAGS = (VERBOSE | MULTILINE | DOTALL)
+class Scanner(object):
+ def __init__(self, lexicon, flags=FLAGS):
+ self.actions = [None]
+ # combine phrases into a compound pattern
+ s = sre_parse.Pattern()
+ s.flags = flags
+ p = []
+ for idx, token in enumerate(lexicon):
+ phrase = token.pattern
+ try:
+ subpattern = sre_parse.SubPattern(s,
+ [(SUBPATTERN, (idx + 1, sre_parse.parse(phrase, flags)))])
+ except sre_constants.error:
+ raise
+ p.append(subpattern)
+ self.actions.append(token)
+
+ p = sre_parse.SubPattern(s, [(BRANCH, (None, p))])
+ self.scanner = sre_compile.compile(p)
+
+
+ def iterscan(self, string, idx=0, context=None):
+ """
+ Yield match, end_idx for each match
+ """
+ match = self.scanner.scanner(string, idx).match
+ actions = self.actions
+ lastend = idx
+ end = len(string)
+ while True:
+ m = match()
+ if m is None:
+ break
+ matchbegin, matchend = m.span()
+ if lastend == matchend:
+ break
+ action = actions[m.lastindex]
+ if action is not None:
+ rval, next_pos = action(m, context)
+ if next_pos is not None and next_pos != matchend:
+ # "fast forward" the scanner
+ matchend = next_pos
+ match = self.scanner.scanner(string, matchend).match
+ yield rval, matchend
+ lastend = matchend
+
+def pattern(pattern, flags=FLAGS):
+ def decorator(fn):
+ fn.pattern = pattern
+ fn.regex = re.compile(pattern, flags)
+ return fn
+ return decorator
diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/elemutil.py b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/elemutil.py
new file mode 100644
index 0000000000..ad971ba6ba
--- /dev/null
+++ b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/elemutil.py
@@ -0,0 +1,168 @@
+# 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.
+
+# Functions to help represent data as lists of elements and attributes
+
+from util import *
+
+element = "'element"
+attribute = "'attribute"
+atsign = "'@"
+
+# Return true if a value is an element
+def isElement(v):
+ if not isList(v) or isNil(v) or v == None or car(v) != element:
+ return False
+ return True
+
+# Return true if a value is an attribute
+def isAttribute(v):
+ if not isList(v) or isNil(v) or v == None or car(v) != attribute:
+ return False
+ return True
+
+# Return the name of attribute
+def attributeName(l):
+ return cadr(l)
+
+# Return the value of attribute
+def attributeValue(l):
+ return caddr(l)
+
+# Return the name of an element
+def elementName(l):
+ return cadr(l)
+
+# Return true if an element has children
+def elementHasChildren(l):
+ return not isNil(cddr(l))
+
+# Return the children of an element
+def elementChildren(l):
+ return cddr(l)
+
+# Return true if an element has a value
+def elementHasValue(l):
+ r = reverse(l)
+ if isSymbol(car(r)):
+ return False
+ if isList(car(r)) and not isNil(car(r)) and isSymbol(car(car(r))):
+ return False
+ return True
+
+# Return the value of an element
+def elementValue(l):
+ return car(reverse(l))
+
+# Convert an element to a value
+def elementToValueIsList(v):
+ if not isList(v):
+ return False
+ return isNil(v) or not isSymbol(car(v))
+
+def elementToValue(t):
+ if isTaggedList(t, attribute):
+ return (atsign + attributeName(t)[1:], attributeValue(t))
+ if isTaggedList(t, element):
+ if elementHasValue(t):
+ if not elementToValueIsList(elementValue(t)):
+ return (elementName(t), elementValue(t))
+ return cons(elementName(t), (elementsToValues(elementValue(t)),))
+ return cons(elementName(t), elementsToValues(elementChildren(t)))
+ if not isList(t):
+ return t
+ return elementsToValues(t)
+
+# Convert a list of elements to a list of values
+def elementToValueIsSymbol(v):
+ if not isList(v):
+ return False
+ if (isNil(v)):
+ return False
+ if not isSymbol(car(v)):
+ return False
+ return True
+
+def elementToValueGroupValues(v, l):
+ if isNil(l) or not elementToValueIsSymbol(v) or not elementToValueIsSymbol(car(l)):
+ return cons(v, l)
+ if car(car(l)) != car(v):
+ return cons(v, l)
+ if not elementToValueIsList(cadr(car(l))):
+ g = (car(v), (cdr(v), cdr(car(l))))
+ return elementToValueGroupValues(g, cdr(l))
+ g = (car(v), cons(cdr(v), cadr(car(l))))
+ return elementToValueGroupValues(g, cdr(l))
+
+def elementsToValues(e):
+ if isNil(e):
+ return e
+ return elementToValueGroupValues(elementToValue(car(e)), elementsToValues(cdr(e)))
+
+# Convert a value to an element
+def valueToElement(t):
+ if isList(t) and not isNil(t) and isSymbol(car(t)):
+ n = car(t)
+ v = cadr(t)
+ if not isList(v):
+ if n[0:2] == atsign:
+ return (attribute, n[1:], v)
+ return (element, n, v)
+ if isNil(v) or not isSymbol(car(v)):
+ return cons(element, cons(n, (valuesToElements(v),)))
+ return cons(element, cons(n, valuesToElements(cdr(t))))
+ if not isList(t):
+ return t
+ return valuesToElements(t)
+
+# Convert a list of values to a list of elements
+def valuesToElements(l):
+ if isNil(l):
+ return l
+ return cons(valueToElement(car(l)), valuesToElements(cdr(l)))
+
+# Return a selector lambda function which can be used to filter elements
+def evalSelect(s, v):
+ if isNil(s):
+ return True
+ if isNil(v):
+ return False
+ if car(s) != car(v):
+ return False
+ return evalSelect(cdr(s), cdr(v))
+
+def selector(s):
+ return lambda v: evalSelect(s, v)
+
+# Return the value of the attribute with the given name
+def namedAttributeValue(name, l):
+ f = filter(lambda v: isAttribute(v) and attributeName(v) == name, l)
+ if isNil(f):
+ return None
+ return caddr(car(f))
+
+# Return child elements with the given name
+def namedElementChildren(name, l):
+ return filter(lambda v: isElement(v) and elementName(v) == name, l)
+
+# Return the child element with the given name
+def namedElementChild(name, l):
+ f = namedElementChildren(name, l)
+ if isNil(f):
+ return None
+ return car(f)
+
diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/invoker.py b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/invoker.py
new file mode 100644
index 0000000000..48107671d6
--- /dev/null
+++ b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/invoker.py
@@ -0,0 +1,108 @@
+#!/usr/bin/python
+# 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.
+
+# Component invocation functions
+
+from sys import stderr, argv
+from util import *
+from jsonutil import *
+
+# JSON request id
+id = 1
+
+# Make a callable reference client
+class proxy:
+ def __init__(self, jpx):
+ self.jpx = jpx
+
+ def __call__(self, func, *args):
+
+ # Create a JSON-RPC request
+ global id
+ req = StringIO()
+ writeStrings(jsonRequest(id, func, args), req)
+ id = id + 1
+
+ # Eval the Java proxy
+ res = self.jpx.eval(req.getvalue())
+
+ # Extract result from JSON-RPC response
+ return jsonResultValue((res,))
+
+ def __repr__(self):
+ return repr((jpx,))
+
+def mkproxies(jpx):
+ if isNil(jpx):
+ return ()
+ return cons(proxy(car(jpx)), mkproxies(cdr(jpx)))
+
+class prop:
+ def __init__(self, jpy):
+ self.jpy = jpy
+
+ def __call__(self):
+ # Eval the property
+ res = self.jpy.eval()
+ return res
+
+def __repr__(self):
+ return repr((jpy,))
+
+def mkprops(jpy):
+ if isNil(jpy):
+ return ()
+ return cons(prop(car(jpy)), mkprops(cdr(jpy)))
+
+# Make a callable component
+class component:
+ def __init__(self, name, impl, jpx, jpy):
+ self.name = name
+ self.impl = impl[0:len(impl) - 3]
+ self.mod = __import__(self.impl)
+ self.proxies = mkproxies(jpx)
+ self.props = mkprops(jpy)
+
+ def __call__(self, func, *args):
+ return self.mod.__getattribute__(func)(*(args + self.proxies + self.props))
+
+ def __repr__(self):
+ return repr((self.name, self.impl, self.mod, self.props, self.proxies))
+
+# Converts the args received in a JSON request to a list of key value pairs
+def jsonArgs(a):
+ if isNil(a):
+ return ((),)
+ l = car(a);
+ return cons(l, jsonArgs(cdr(a)))
+
+# Apply a JSON function request to a component
+def apply(jsreq, comp):
+ json = elementsToValues(readJSON((jsreq,)))
+ args = jsonArgs(json)
+ jid = cadr(assoc("'id", args))
+ func = funcName(cadr(assoc("'method", args)))
+ params = cadr(assoc("'params", args))
+ v = comp(func, *params)
+ return jsonResult(jid, v)[0]
+
+# Make a component that can be called with a JSON function request
+def mkcomponent(name, impl, jpx, jpy):
+ comp = component(name, impl, jpx, jpy)
+ return lambda jsreq: apply(jsreq, comp)
+
diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/jsonutil.py b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/jsonutil.py
new file mode 100644
index 0000000000..f69559de54
--- /dev/null
+++ b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/jsonutil.py
@@ -0,0 +1,142 @@
+# 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.
+
+# JSON data conversion functions
+
+try:
+ import json
+except:
+ from django.utils import simplejson as json
+
+from StringIO import StringIO
+from util import *
+from elemutil import *
+
+# Return true if a list represents a JS array
+def isJSArray(l):
+ if isNil(l):
+ return True
+ v = car(l)
+ if isSymbol(v):
+ return False
+ if isList(v):
+ if not isNil(v) and isSymbol(car(v)):
+ return False
+ return True
+
+# Converts JSON properties to values
+def jsPropertiesToValues(propertiesSoFar, o, i):
+ if isNil(i):
+ return propertiesSoFar
+ p = car(i)
+ jsv = o[p]
+ v = jsValToValue(jsv)
+
+ if isinstance(p, basestring):
+ n = str(p)
+ if n[0:1] == "@":
+ return jsPropertiesToValues(cons((attribute, "'" + n[1:], v), propertiesSoFar), o, cdr(i))
+ if isList(v) and not isJSArray(v):
+ return jsPropertiesToValues(cons(cons(element, cons("'" + n, v)), propertiesSoFar), o, cdr(i))
+ return jsPropertiesToValues(cons((element, "'" + n, v), propertiesSoFar), o, cdr(i))
+ return jsPropertiesToValues(cons(v, propertiesSoFar), o, cdr(i))
+
+# Converts a JSON val to a value
+def jsValToValue(jsv):
+ if isinstance(jsv, dict):
+ return jsPropertiesToValues((), jsv, tuple(jsv.keys()))
+ if isList(jsv):
+ return jsPropertiesToValues((), jsv, tuple(reversed(range(0, len(jsv)))))
+ if isinstance(jsv, basestring):
+ return str(jsv)
+ return jsv
+
+# Convert a list of strings representing a JSON document to a list of values
+def readJSON(l):
+ s = StringIO()
+ writeStrings(l, s)
+ val = json.loads(s.getvalue())
+ return jsValToValue(val)
+
+# Convert a list of values to JSON array elements
+def valuesToJSElements(a, l, i):
+ if isNil(l):
+ return a
+ pv = valueToJSVal(car(l))
+ a[i] = pv
+ return valuesToJSElements(a, cdr(l), i + 1)
+
+# Convert a value to a JSON value
+def valueToJSVal(v):
+ if not isList(v):
+ return v
+ if isJSArray(v):
+ return valuesToJSElements(list(range(0, len(v))), v, 0)
+ return valuesToJSProperties({}, v)
+
+# Convert a list of values to JSON properties
+def valuesToJSProperties(o, l):
+ if isNil(l):
+ return o
+ token = car(l)
+ if isTaggedList(token, attribute):
+ pv = valueToJSVal(attributeValue(token))
+ o["@" + attributeName(token)[1:]] = pv
+ elif isTaggedList(token, element):
+ if elementHasValue(token):
+ pv = valueToJSVal(elementValue(token))
+ o[elementName(token)[1:]] = pv
+ else:
+ child = {}
+ o[elementName(token)[1:]] = child
+ valuesToJSProperties(child, elementChildren(token))
+ return valuesToJSProperties(o, cdr(l))
+
+# Convert a list of values to a list of strings representing a JSON document
+def writeJSON(l):
+ jsv = valuesToJSProperties({}, l)
+ s = json.dumps(jsv, separators=(',',':'))
+ return (s,)
+
+# Convert a list + params to a JSON-RPC request
+def jsonRequest(id, func, params):
+ r = (("'id", id), ("'method", func), ("'params", params))
+ return writeJSON(valuesToElements(r))
+
+# Convert a value to a JSON-RPC result
+def jsonResult(id, val):
+ return writeJSON(valuesToElements((("'id", id), ("'result", val))))
+
+# Convert a JSON-RPC result to a value
+def jsonResultValue(s):
+ jsres = readJSON(s)
+ res = elementsToValues(jsres)
+ val = cadr(assoc("'result", res))
+ if isList(val) and not isJSArray(val):
+ return (val,)
+ return val
+
+# Return a portable function name from a JSON-RPC function name
+def funcName(f):
+ if f.startswith("."):
+ return f[1:]
+ if f.startswith("system."):
+ return f[7:]
+ if f.startswith("Service."):
+ return f[8:]
+ return f
+
diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/rssutil.py b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/rssutil.py
new file mode 100644
index 0000000000..4f060d2321
--- /dev/null
+++ b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/rssutil.py
@@ -0,0 +1,119 @@
+# 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.
+
+# RSS data conversion functions
+
+from util import *
+from elemutil import *
+from xmlutil import *
+
+# Convert a list of elements to a list of values representing an RSS entry
+def entryElementsToValues(e):
+ lt = filter(selector((element, "'title")), e)
+ t = "" if isNil(lt) else elementValue(car(lt))
+ li = filter(selector((element, "'link")), e)
+ i = "" if isNil(li) else elementValue(car(li))
+ lc = filter(selector((element, "'description")), e)
+ return (t, i, elementValue(car(lc)))
+
+# Convert a list of elements to a list of values representing RSS entries
+def entriesElementsToValues(e):
+ if isNil(e):
+ return e
+ return cons(entryElementsToValues(car(e)), entriesElementsToValues(cdr(e)))
+
+# Convert a list of strings to a list of values representing an RSS entry
+def readRSSEntry(l):
+ e = readXML(l)
+ if isNil(e):
+ return ()
+ return entryElementsToValues(car(e))
+
+# Convert a list of values representy an RSS entry to a value
+def entryValue(e):
+ v = elementsToValues((caddr(e),))
+ return cons(car(e), (cadr(e), cdr(car(v))))
+
+# Return true if a list of strings represents an RSS feed
+def isRSSFeed(l):
+ if isNil(l):
+ return False
+ if car(l)[0:5] != "<?xml":
+ return False
+ return contains(car(l), "<rss")
+
+# Convert a list of strings to a list of values representing an RSS feed
+def readRSSFeed(l):
+ f = readXML(l)
+ if isNil(f):
+ return ()
+ c = filter(selector((element, "'channel")), car(f))
+ t = filter(selector((element, "'title")), car(c))
+ i = filter(selector((element, "'link")), car(c))
+ e = filter(selector((element, "'item")), car(c))
+ if isNil(e):
+ return (elementValue(car(t)), elementValue(car(i)))
+ return cons(elementValue(car(t)), cons(elementValue(car(i)), entriesElementsToValues(e)))
+
+# Convert an RSS feed containing elements to an RSS feed containing values
+def feedValuesLoop(e):
+ if (isNil(e)):
+ return e
+ return cons(entryValue(car(e)), feedValuesLoop(cdr(e)))
+
+def feedValues(e):
+ return cons(car(e), cons(cadr(e), feedValuesLoop(cddr(e))))
+
+# Convert a list of values representy an RSS entry to a list of elements
+def entryElement(l):
+ return (element, "'item",
+ (element, "'title", car(l)),
+ (element, "'link", cadr(l)),
+ (element, "'description", caddr(l)))
+
+# Convert a list of values representing RSS entries to a list of elements
+def entriesElements(l):
+ if isNil(l):
+ return l
+ return cons(entryElement(car(l)), entriesElements(cdr(l)))
+
+# Convert a list of values representing an RSS entry to an RSS entry
+def writeRSSEntry(l):
+ return writeXML((entryElement(l),), True)
+
+# Convert a list of values representing an RSS feed to an RSS feed
+def writeRSSFeed(l):
+ c = ((element, "'title", car(l)),
+ (element, "'link", cadr(l)),
+ (element, "'description", car(l)))
+ ce = c if isNil(cddr(l)) else append(c, entriesElements(cddr(l)))
+ fe = (element, "'rss", (attribute, "'version", "2.0"), append((element, "'channel"), ce))
+ return writeXML((fe,), True)
+
+# Convert an RSS entry containing a value to an RSS entry containing an item element
+def entryValuesToElements(v):
+ return cons(car(v), cons(cadr(v), valuesToElements((cons("'item", caddr(v)),))))
+
+# Convert an RSS feed containing values to an RSS feed containing elements
+def feedValuesToElementsLoop(v):
+ if isNil(v):
+ return v
+ return cons(entryValuesToElements(car(v)), feedValuesToElementsLoop(cdr(v)))
+
+def feedValuesToElements(v):
+ return cons(car(v), cons(cadr(v), feedValuesToElementsLoop(cddr(v))))
+
diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/util.py b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/util.py
new file mode 100644
index 0000000000..560101e32d
--- /dev/null
+++ b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/util.py
@@ -0,0 +1,145 @@
+# 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.
+
+# Simple utility functions
+from sys import maxint
+
+# Scheme-like lists
+def cons(a, b):
+ return (a,) + b
+
+def car(l):
+ return l[0]
+
+def first(l):
+ return car(l)
+
+def cdr(l):
+ return l[1:]
+
+def rest(l):
+ return cdr(l)
+
+def cadr(l):
+ return car(cdr(l))
+
+def cddr(l):
+ return cdr(cdr(l))
+
+def caddr(l):
+ return car(cddr(l))
+
+def append(a, b):
+ return a + b
+
+def reverse(l):
+ r = list(l)
+ r.reverse()
+ return tuple(r)
+
+def isNil(l):
+ if isinstance(l, streampair):
+ return l.isNil()
+ return l == ()
+
+def isSymbol(v):
+ return isinstance(v, basestring) and v[0:1] == "'"
+
+def isList(v):
+ if getattr(v, '__iter__', False) == False:
+ return False
+ if isinstance(v, basestring) or isinstance(v, dict):
+ return False
+ return True
+
+def isTaggedList(v, t):
+ return isList(v) and not isNil(v) and car(v) == t
+
+
+# Scheme-like streams
+class streampair(object):
+ def __init__(self, car, cdr):
+ self.car = car
+ self.cdr = cdr
+
+ def __repr__(self):
+ return repr(self[0:len(self)])
+
+ def isNil(self):
+ return self.cdr == ()
+
+ def __len__(self):
+ if self.cdr == ():
+ return 0
+ return 1 + len(self.cdr())
+
+ def __getitem__(self, i):
+ if i == 0:
+ return self.car
+ return self.cdr()[i - 1]
+
+ def __getslice__(self, i, j):
+ if isNil(self):
+ return ()
+ if i > 0:
+ if j == maxint:
+ return self.cdr()[i - 1: j]
+ return self.cdr()[i - 1: j - 1]
+ if j == maxint:
+ return self
+ if j == 0:
+ return (self.car,)
+ return (self.car,) + self.cdr()[: j - 1]
+
+ def __eq__(self, other):
+ sl = len(self)
+ ol = len(other)
+ if sl != ol:
+ return False
+ return self[0: sl] == other[0: ol]
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+def cons_stream(car, cdr):
+ return streampair(car, cdr)
+
+
+# Scheme-like associations
+def assoc(k, l):
+ if l == ():
+ return None
+
+ if k == car(car(l)):
+ return car(l)
+ return assoc(k, cdr(l))
+
+# Currying / partial function application
+def curry(f, *args):
+ return lambda *a: f(*(args + a))
+
+# Split a path into a list of segments
+def tokens(path):
+ return tuple(filter(lambda s: len(s) != 0, path.split("/")))
+
+# Write a list of strings to a stream
+def writeStrings(l, os):
+ if l == ():
+ return os
+ os.write(car(l))
+ return writeStrings(cdr(l), os)
+
diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/xmlutil.py b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/xmlutil.py
new file mode 100644
index 0000000000..a1bc04629a
--- /dev/null
+++ b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-python-runtime/src/main/resources/xmlutil.py
@@ -0,0 +1,114 @@
+# 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.
+
+# XML handling functions
+
+from StringIO import StringIO
+from xml.parsers import expat
+import xml.etree.ElementTree as et
+from util import *
+from elemutil import *
+
+# Read a list of XML attributes
+def readAttributes(a):
+ if a == ():
+ return a
+ return cons((attribute, "'" + car(car(a)), cadr(car(a))), readAttributes(cdr(a)))
+
+# Read an XML element
+def readElement(e):
+ l = (element, "'" + e.tag) + readAttributes(tuple(e.items())) + readElements(tuple(e.getchildren()))
+ if e.text == None:
+ return l
+ return l + (e.text,)
+
+# Read a list of XML elements
+def readElements(l):
+ if l == ():
+ return l
+ return cons(readElement(car(l)), readElements(cdr(l)))
+
+# Parse a list of strings representing an XML document
+class NamespaceParser(et.XMLTreeBuilder):
+ def __init__(self):
+ et.XMLTreeBuilder.__init__(self)
+ self._parser = parser = expat.ParserCreate(None)
+ parser.DefaultHandlerExpand = self._default
+ parser.StartElementHandler = self._start
+ parser.EndElementHandler = self._end
+ parser.CharacterDataHandler = self._data
+ try:
+ parser.buffer_text = 1
+ except AttributeError:
+ pass
+ try:
+ parser.ordered_attributes = 1
+ parser.specified_attributes = 1
+ parser.StartElementHandler = self._start_list
+ except AttributeError:
+ pass
+
+def parseXML(l):
+ s = StringIO()
+ writeStrings(l, s)
+ parser = NamespaceParser()
+ parser.feed(s.getvalue())
+ return parser.close()
+
+# Read a list of values from a list of strings representing an XML document
+def readXML(l):
+ e = parseXML(l)
+ return (readElement(e),)
+
+# Write a list of XML element and attribute tokens
+def expandElementValues(n, l):
+ if isNil(l):
+ return l
+ return cons(cons(element, cons(n, car(l))), expandElementValues(n, cdr(l)))
+
+def writeList(l, xml):
+ if isNil(l):
+ return xml
+ token = car(l)
+ if isTaggedList(token, attribute):
+ xml.attrib[attributeName(token)[1:]] = str(attributeValue(token))
+ elif isTaggedList(token, element):
+ if elementHasValue(token):
+ v = elementValue(token)
+ if isList(v):
+ e = expandElementValues(elementName(token), v)
+ writeList(e, xml)
+ else:
+ child = et.Element(elementName(token)[1:])
+ writeList(elementChildren(token), child)
+ xml.append(child)
+ else:
+ child = et.Element(elementName(token)[1:])
+ writeList(elementChildren(token), child)
+ xml.append(child)
+ else:
+ xml.text = str(token)
+ writeList(cdr(l), xml)
+ return xml
+
+# Convert a list of values to a list of strings representing an XML document
+def writeXML(l, xmlTag):
+ e = writeList(l, [])
+ if not xmlTag:
+ return (et.tostring(car(e)),)
+ return (et.tostring(car(e), "UTF-8") + "\n",)
+