src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/JAXPExtensionsProvider.java
author joehw
Wed, 18 Oct 2017 13:25:49 -0700
changeset 47359 e1a6c0168741
parent 47216 71c04702a3d5
child 47712 bde0215f1f70
permissions -rw-r--r--
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked Reviewed-by: lancea, rriggs, mullan
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
6
7f561c08de6b Initial load
duke
parents:
diff changeset
     1
/*
47359
e1a6c0168741 8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents: 47216
diff changeset
     2
 * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
e1a6c0168741 8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents: 47216
diff changeset
     3
 * @LastModified: Oct 2017
6
7f561c08de6b Initial load
duke
parents:
diff changeset
     4
 */
7f561c08de6b Initial load
duke
parents:
diff changeset
     5
/*
39907
db51759e3695 8158084: Catalog API: JAXP XML Processor Support
joehw
parents: 25868
diff changeset
     6
 * Licensed to the Apache Software Foundation (ASF) under one or more
db51759e3695 8158084: Catalog API: JAXP XML Processor Support
joehw
parents: 25868
diff changeset
     7
 * contributor license agreements.  See the NOTICE file distributed with
db51759e3695 8158084: Catalog API: JAXP XML Processor Support
joehw
parents: 25868
diff changeset
     8
 * this work for additional information regarding copyright ownership.
db51759e3695 8158084: Catalog API: JAXP XML Processor Support
joehw
parents: 25868
diff changeset
     9
 * The ASF licenses this file to You under the Apache License, Version 2.0
db51759e3695 8158084: Catalog API: JAXP XML Processor Support
joehw
parents: 25868
diff changeset
    10
 * (the "License"); you may not use this file except in compliance with
db51759e3695 8158084: Catalog API: JAXP XML Processor Support
joehw
parents: 25868
diff changeset
    11
 * the License.  You may obtain a copy of the License at
6
7f561c08de6b Initial load
duke
parents:
diff changeset
    12
 *
39907
db51759e3695 8158084: Catalog API: JAXP XML Processor Support
joehw
parents: 25868
diff changeset
    13
 *      http://www.apache.org/licenses/LICENSE-2.0
6
7f561c08de6b Initial load
duke
parents:
diff changeset
    14
 *
7f561c08de6b Initial load
duke
parents:
diff changeset
    15
 * Unless required by applicable law or agreed to in writing, software
7f561c08de6b Initial load
duke
parents:
diff changeset
    16
 * distributed under the License is distributed on an "AS IS" BASIS,
7f561c08de6b Initial load
duke
parents:
diff changeset
    17
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
7f561c08de6b Initial load
duke
parents:
diff changeset
    18
 * See the License for the specific language governing permissions and
7f561c08de6b Initial load
duke
parents:
diff changeset
    19
 * limitations under the License.
7f561c08de6b Initial load
duke
parents:
diff changeset
    20
 */
7f561c08de6b Initial load
duke
parents:
diff changeset
    21
7f561c08de6b Initial load
duke
parents:
diff changeset
    22
package com.sun.org.apache.xpath.internal.jaxp;
7f561c08de6b Initial load
duke
parents:
diff changeset
    23
39907
db51759e3695 8158084: Catalog API: JAXP XML Processor Support
joehw
parents: 25868
diff changeset
    24
import com.sun.org.apache.xalan.internal.res.XSLMessages;
db51759e3695 8158084: Catalog API: JAXP XML Processor Support
joehw
parents: 25868
diff changeset
    25
import com.sun.org.apache.xpath.internal.ExtensionsProvider;
db51759e3695 8158084: Catalog API: JAXP XML Processor Support
joehw
parents: 25868
diff changeset
    26
import com.sun.org.apache.xpath.internal.functions.FuncExtFunction;
db51759e3695 8158084: Catalog API: JAXP XML Processor Support
joehw
parents: 25868
diff changeset
    27
import com.sun.org.apache.xpath.internal.objects.XNodeSet;
db51759e3695 8158084: Catalog API: JAXP XML Processor Support
joehw
parents: 25868
diff changeset
    28
import com.sun.org.apache.xpath.internal.objects.XObject;
db51759e3695 8158084: Catalog API: JAXP XML Processor Support
joehw
parents: 25868
diff changeset
    29
import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
db51759e3695 8158084: Catalog API: JAXP XML Processor Support
joehw
parents: 25868
diff changeset
    30
import java.util.ArrayList;
47359
e1a6c0168741 8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents: 47216
diff changeset
    31
import java.util.List;
39907
db51759e3695 8158084: Catalog API: JAXP XML Processor Support
joehw
parents: 25868
diff changeset
    32
import javax.xml.namespace.QName;
6
7f561c08de6b Initial load
duke
parents:
diff changeset
    33
import javax.xml.xpath.XPathFunction;
7f561c08de6b Initial load
duke
parents:
diff changeset
    34
import javax.xml.xpath.XPathFunctionException;
39907
db51759e3695 8158084: Catalog API: JAXP XML Processor Support
joehw
parents: 25868
diff changeset
    35
import javax.xml.xpath.XPathFunctionResolver;
db51759e3695 8158084: Catalog API: JAXP XML Processor Support
joehw
parents: 25868
diff changeset
    36
import jdk.xml.internal.JdkXmlFeatures;
6
7f561c08de6b Initial load
duke
parents:
diff changeset
    37
7f561c08de6b Initial load
duke
parents:
diff changeset
    38
/**
7f561c08de6b Initial load
duke
parents:
diff changeset
    39
 *
7f561c08de6b Initial load
duke
parents:
diff changeset
    40
 * @author Ramesh Mandava ( ramesh.mandava@sun.com )
7f561c08de6b Initial load
duke
parents:
diff changeset
    41
 */
7f561c08de6b Initial load
duke
parents:
diff changeset
    42
public class JAXPExtensionsProvider implements ExtensionsProvider {
7f561c08de6b Initial load
duke
parents:
diff changeset
    43
7f561c08de6b Initial load
duke
parents:
diff changeset
    44
    private final XPathFunctionResolver resolver;
7f561c08de6b Initial load
duke
parents:
diff changeset
    45
    private boolean extensionInvocationDisabled = false;
7f561c08de6b Initial load
duke
parents:
diff changeset
    46
7f561c08de6b Initial load
duke
parents:
diff changeset
    47
    public JAXPExtensionsProvider(XPathFunctionResolver resolver) {
7f561c08de6b Initial load
duke
parents:
diff changeset
    48
        this.resolver = resolver;
7f561c08de6b Initial load
duke
parents:
diff changeset
    49
        this.extensionInvocationDisabled = false;
7f561c08de6b Initial load
duke
parents:
diff changeset
    50
    }
7f561c08de6b Initial load
duke
parents:
diff changeset
    51
7f561c08de6b Initial load
duke
parents:
diff changeset
    52
    public JAXPExtensionsProvider(XPathFunctionResolver resolver,
39907
db51759e3695 8158084: Catalog API: JAXP XML Processor Support
joehw
parents: 25868
diff changeset
    53
        boolean featureSecureProcessing, JdkXmlFeatures featureManager ) {
6
7f561c08de6b Initial load
duke
parents:
diff changeset
    54
        this.resolver = resolver;
21467
ed77f0ff062c 8004476: XSLT Extension Functions Don't Work in WebStart
joehw
parents: 12457
diff changeset
    55
        if (featureSecureProcessing &&
39907
db51759e3695 8158084: Catalog API: JAXP XML Processor Support
joehw
parents: 25868
diff changeset
    56
                !featureManager.getFeature(JdkXmlFeatures.XmlFeature.ENABLE_EXTENSION_FUNCTION)) {
21467
ed77f0ff062c 8004476: XSLT Extension Functions Don't Work in WebStart
joehw
parents: 12457
diff changeset
    57
            this.extensionInvocationDisabled = true;
ed77f0ff062c 8004476: XSLT Extension Functions Don't Work in WebStart
joehw
parents: 12457
diff changeset
    58
        }
6
7f561c08de6b Initial load
duke
parents:
diff changeset
    59
    }
7f561c08de6b Initial load
duke
parents:
diff changeset
    60
7f561c08de6b Initial load
duke
parents:
diff changeset
    61
    /**
7f561c08de6b Initial load
duke
parents:
diff changeset
    62
     * Is the extension function available?
7f561c08de6b Initial load
duke
parents:
diff changeset
    63
     */
7f561c08de6b Initial load
duke
parents:
diff changeset
    64
7f561c08de6b Initial load
duke
parents:
diff changeset
    65
    public boolean functionAvailable(String ns, String funcName)
7f561c08de6b Initial load
duke
parents:
diff changeset
    66
          throws javax.xml.transform.TransformerException {
7f561c08de6b Initial load
duke
parents:
diff changeset
    67
      try {
7f561c08de6b Initial load
duke
parents:
diff changeset
    68
        if ( funcName == null ) {
7f561c08de6b Initial load
duke
parents:
diff changeset
    69
            String fmsg = XSLMessages.createXPATHMessage(
7f561c08de6b Initial load
duke
parents:
diff changeset
    70
                XPATHErrorResources.ER_ARG_CANNOT_BE_NULL,
7f561c08de6b Initial load
duke
parents:
diff changeset
    71
                new Object[] {"Function Name"} );
7f561c08de6b Initial load
duke
parents:
diff changeset
    72
            throw new NullPointerException ( fmsg );
7f561c08de6b Initial load
duke
parents:
diff changeset
    73
        }
7f561c08de6b Initial load
duke
parents:
diff changeset
    74
        //Find the XPathFunction corresponding to namespace and funcName
7f561c08de6b Initial load
duke
parents:
diff changeset
    75
        javax.xml.namespace.QName myQName = new QName( ns, funcName );
7f561c08de6b Initial load
duke
parents:
diff changeset
    76
        javax.xml.xpath.XPathFunction xpathFunction =
7f561c08de6b Initial load
duke
parents:
diff changeset
    77
            resolver.resolveFunction ( myQName, 0 );
7f561c08de6b Initial load
duke
parents:
diff changeset
    78
        if (  xpathFunction == null ) {
7f561c08de6b Initial load
duke
parents:
diff changeset
    79
            return false;
7f561c08de6b Initial load
duke
parents:
diff changeset
    80
        }
7f561c08de6b Initial load
duke
parents:
diff changeset
    81
        return true;
7f561c08de6b Initial load
duke
parents:
diff changeset
    82
      } catch ( Exception e ) {
7f561c08de6b Initial load
duke
parents:
diff changeset
    83
        return false;
7f561c08de6b Initial load
duke
parents:
diff changeset
    84
      }
7f561c08de6b Initial load
duke
parents:
diff changeset
    85
7f561c08de6b Initial load
duke
parents:
diff changeset
    86
7f561c08de6b Initial load
duke
parents:
diff changeset
    87
    }
7f561c08de6b Initial load
duke
parents:
diff changeset
    88
7f561c08de6b Initial load
duke
parents:
diff changeset
    89
7f561c08de6b Initial load
duke
parents:
diff changeset
    90
    /**
7f561c08de6b Initial load
duke
parents:
diff changeset
    91
     * Is the extension element available?
7f561c08de6b Initial load
duke
parents:
diff changeset
    92
     */
7f561c08de6b Initial load
duke
parents:
diff changeset
    93
    public boolean elementAvailable(String ns, String elemName)
7f561c08de6b Initial load
duke
parents:
diff changeset
    94
          throws javax.xml.transform.TransformerException {
7f561c08de6b Initial load
duke
parents:
diff changeset
    95
        return false;
7f561c08de6b Initial load
duke
parents:
diff changeset
    96
    }
7f561c08de6b Initial load
duke
parents:
diff changeset
    97
7f561c08de6b Initial load
duke
parents:
diff changeset
    98
    /**
7f561c08de6b Initial load
duke
parents:
diff changeset
    99
     * Execute the extension function.
7f561c08de6b Initial load
duke
parents:
diff changeset
   100
     */
47359
e1a6c0168741 8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents: 47216
diff changeset
   101
    public Object extFunction(String ns, String funcName, List<XObject> argVec,
6
7f561c08de6b Initial load
duke
parents:
diff changeset
   102
        Object methodKey) throws javax.xml.transform.TransformerException {
7f561c08de6b Initial load
duke
parents:
diff changeset
   103
        try {
7f561c08de6b Initial load
duke
parents:
diff changeset
   104
7f561c08de6b Initial load
duke
parents:
diff changeset
   105
            if ( funcName == null ) {
7f561c08de6b Initial load
duke
parents:
diff changeset
   106
                String fmsg = XSLMessages.createXPATHMessage(
7f561c08de6b Initial load
duke
parents:
diff changeset
   107
                    XPATHErrorResources.ER_ARG_CANNOT_BE_NULL,
7f561c08de6b Initial load
duke
parents:
diff changeset
   108
                    new Object[] {"Function Name"} );
7f561c08de6b Initial load
duke
parents:
diff changeset
   109
                throw new NullPointerException ( fmsg );
7f561c08de6b Initial load
duke
parents:
diff changeset
   110
            }
7f561c08de6b Initial load
duke
parents:
diff changeset
   111
            //Find the XPathFunction corresponding to namespace and funcName
7f561c08de6b Initial load
duke
parents:
diff changeset
   112
            javax.xml.namespace.QName myQName = new QName( ns, funcName );
7f561c08de6b Initial load
duke
parents:
diff changeset
   113
7f561c08de6b Initial load
duke
parents:
diff changeset
   114
            // JAXP 1.3 spec says When XMLConstants.FEATURE_SECURE_PROCESSING
7f561c08de6b Initial load
duke
parents:
diff changeset
   115
            // feature is set then invocation of extension functions need to
7f561c08de6b Initial load
duke
parents:
diff changeset
   116
            // throw XPathFunctionException
7f561c08de6b Initial load
duke
parents:
diff changeset
   117
            if ( extensionInvocationDisabled ) {
7f561c08de6b Initial load
duke
parents:
diff changeset
   118
                String fmsg = XSLMessages.createXPATHMessage(
7f561c08de6b Initial load
duke
parents:
diff changeset
   119
                    XPATHErrorResources.ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED,
7f561c08de6b Initial load
duke
parents:
diff changeset
   120
                    new Object[] { myQName.toString() } );
7f561c08de6b Initial load
duke
parents:
diff changeset
   121
                throw new XPathFunctionException ( fmsg );
7f561c08de6b Initial load
duke
parents:
diff changeset
   122
            }
7f561c08de6b Initial load
duke
parents:
diff changeset
   123
7f561c08de6b Initial load
duke
parents:
diff changeset
   124
            // Assuming user is passing all the needed parameters ( including
7f561c08de6b Initial load
duke
parents:
diff changeset
   125
            // default values )
7f561c08de6b Initial load
duke
parents:
diff changeset
   126
            int arity = argVec.size();
7f561c08de6b Initial load
duke
parents:
diff changeset
   127
7f561c08de6b Initial load
duke
parents:
diff changeset
   128
            javax.xml.xpath.XPathFunction xpathFunction =
7f561c08de6b Initial load
duke
parents:
diff changeset
   129
                resolver.resolveFunction ( myQName, arity );
7f561c08de6b Initial load
duke
parents:
diff changeset
   130
7f561c08de6b Initial load
duke
parents:
diff changeset
   131
            // not using methodKey
47359
e1a6c0168741 8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents: 47216
diff changeset
   132
            List<Object> argList = new ArrayList<>( arity);
6
7f561c08de6b Initial load
duke
parents:
diff changeset
   133
            for ( int i=0; i<arity; i++ ) {
47359
e1a6c0168741 8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents: 47216
diff changeset
   134
                XObject argument = argVec.get( i );
6
7f561c08de6b Initial load
duke
parents:
diff changeset
   135
                // XNodeSet object() returns NodeVector and not NodeList
7f561c08de6b Initial load
duke
parents:
diff changeset
   136
                // Explicitly getting NodeList by using nodelist()
7f561c08de6b Initial load
duke
parents:
diff changeset
   137
                if ( argument instanceof XNodeSet ) {
7f561c08de6b Initial load
duke
parents:
diff changeset
   138
                    argList.add ( i, ((XNodeSet)argument).nodelist() );
7f561c08de6b Initial load
duke
parents:
diff changeset
   139
                } else if ( argument instanceof XObject ) {
7f561c08de6b Initial load
duke
parents:
diff changeset
   140
                    Object passedArgument = ((XObject)argument).object();
7f561c08de6b Initial load
duke
parents:
diff changeset
   141
                    argList.add ( i, passedArgument );
7f561c08de6b Initial load
duke
parents:
diff changeset
   142
                } else {
7f561c08de6b Initial load
duke
parents:
diff changeset
   143
                    argList.add ( i, argument );
7f561c08de6b Initial load
duke
parents:
diff changeset
   144
                }
7f561c08de6b Initial load
duke
parents:
diff changeset
   145
            }
7f561c08de6b Initial load
duke
parents:
diff changeset
   146
7f561c08de6b Initial load
duke
parents:
diff changeset
   147
            return ( xpathFunction.evaluate ( argList ));
7f561c08de6b Initial load
duke
parents:
diff changeset
   148
        } catch ( XPathFunctionException xfe ) {
7f561c08de6b Initial load
duke
parents:
diff changeset
   149
            // If we get XPathFunctionException then we want to terminate
7f561c08de6b Initial load
duke
parents:
diff changeset
   150
            // further execution by throwing WrappedRuntimeException
7f561c08de6b Initial load
duke
parents:
diff changeset
   151
            throw new com.sun.org.apache.xml.internal.utils.WrappedRuntimeException ( xfe );
7f561c08de6b Initial load
duke
parents:
diff changeset
   152
        } catch ( Exception e ) {
7f561c08de6b Initial load
duke
parents:
diff changeset
   153
            throw new javax.xml.transform.TransformerException ( e );
7f561c08de6b Initial load
duke
parents:
diff changeset
   154
        }
7f561c08de6b Initial load
duke
parents:
diff changeset
   155
7f561c08de6b Initial load
duke
parents:
diff changeset
   156
    }
7f561c08de6b Initial load
duke
parents:
diff changeset
   157
7f561c08de6b Initial load
duke
parents:
diff changeset
   158
    /**
7f561c08de6b Initial load
duke
parents:
diff changeset
   159
     * Execute the extension function.
7f561c08de6b Initial load
duke
parents:
diff changeset
   160
     */
47359
e1a6c0168741 8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents: 47216
diff changeset
   161
    public Object extFunction(FuncExtFunction extFunction, List<XObject> argVec)
6
7f561c08de6b Initial load
duke
parents:
diff changeset
   162
        throws javax.xml.transform.TransformerException {
7f561c08de6b Initial load
duke
parents:
diff changeset
   163
        try {
7f561c08de6b Initial load
duke
parents:
diff changeset
   164
            String namespace = extFunction.getNamespace();
7f561c08de6b Initial load
duke
parents:
diff changeset
   165
            String functionName = extFunction.getFunctionName();
7f561c08de6b Initial load
duke
parents:
diff changeset
   166
            int arity = extFunction.getArgCount();
7f561c08de6b Initial load
duke
parents:
diff changeset
   167
            javax.xml.namespace.QName myQName =
7f561c08de6b Initial load
duke
parents:
diff changeset
   168
                new javax.xml.namespace.QName( namespace, functionName );
7f561c08de6b Initial load
duke
parents:
diff changeset
   169
7f561c08de6b Initial load
duke
parents:
diff changeset
   170
            // JAXP 1.3 spec says  When XMLConstants.FEATURE_SECURE_PROCESSING
7f561c08de6b Initial load
duke
parents:
diff changeset
   171
            // feature is set then invocation of extension functions need to
7f561c08de6b Initial load
duke
parents:
diff changeset
   172
            // throw XPathFunctionException
7f561c08de6b Initial load
duke
parents:
diff changeset
   173
            if ( extensionInvocationDisabled ) {
7f561c08de6b Initial load
duke
parents:
diff changeset
   174
                String fmsg = XSLMessages.createXPATHMessage(
47359
e1a6c0168741 8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents: 47216
diff changeset
   175
                    XPATHErrorResources.ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED,
e1a6c0168741 8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents: 47216
diff changeset
   176
                        new Object[] { myQName.toString() } );
6
7f561c08de6b Initial load
duke
parents:
diff changeset
   177
                throw new XPathFunctionException ( fmsg );
7f561c08de6b Initial load
duke
parents:
diff changeset
   178
            }
7f561c08de6b Initial load
duke
parents:
diff changeset
   179
7f561c08de6b Initial load
duke
parents:
diff changeset
   180
            XPathFunction xpathFunction =
7f561c08de6b Initial load
duke
parents:
diff changeset
   181
                resolver.resolveFunction( myQName, arity );
7f561c08de6b Initial load
duke
parents:
diff changeset
   182
47359
e1a6c0168741 8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents: 47216
diff changeset
   183
            List<Object> argList = new ArrayList<>( arity);
6
7f561c08de6b Initial load
duke
parents:
diff changeset
   184
            for ( int i=0; i<arity; i++ ) {
47359
e1a6c0168741 8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents: 47216
diff changeset
   185
                XObject argument = argVec.get( i );
6
7f561c08de6b Initial load
duke
parents:
diff changeset
   186
                // XNodeSet object() returns NodeVector and not NodeList
7f561c08de6b Initial load
duke
parents:
diff changeset
   187
                // Explicitly getting NodeList by using nodelist()
7f561c08de6b Initial load
duke
parents:
diff changeset
   188
                if ( argument instanceof XNodeSet ) {
7f561c08de6b Initial load
duke
parents:
diff changeset
   189
                    argList.add ( i, ((XNodeSet)argument).nodelist() );
7f561c08de6b Initial load
duke
parents:
diff changeset
   190
                } else if ( argument instanceof XObject ) {
7f561c08de6b Initial load
duke
parents:
diff changeset
   191
                    Object passedArgument = ((XObject)argument).object();
7f561c08de6b Initial load
duke
parents:
diff changeset
   192
                    argList.add ( i, passedArgument );
7f561c08de6b Initial load
duke
parents:
diff changeset
   193
                } else {
7f561c08de6b Initial load
duke
parents:
diff changeset
   194
                    argList.add ( i, argument );
7f561c08de6b Initial load
duke
parents:
diff changeset
   195
                }
7f561c08de6b Initial load
duke
parents:
diff changeset
   196
            }
7f561c08de6b Initial load
duke
parents:
diff changeset
   197
7f561c08de6b Initial load
duke
parents:
diff changeset
   198
            return ( xpathFunction.evaluate ( argList ));
7f561c08de6b Initial load
duke
parents:
diff changeset
   199
7f561c08de6b Initial load
duke
parents:
diff changeset
   200
        } catch ( XPathFunctionException xfe ) {
7f561c08de6b Initial load
duke
parents:
diff changeset
   201
            // If we get XPathFunctionException then we want to terminate
7f561c08de6b Initial load
duke
parents:
diff changeset
   202
            // further execution by throwing WrappedRuntimeException
7f561c08de6b Initial load
duke
parents:
diff changeset
   203
            throw new com.sun.org.apache.xml.internal.utils.WrappedRuntimeException ( xfe );
7f561c08de6b Initial load
duke
parents:
diff changeset
   204
        } catch ( Exception e ) {
7f561c08de6b Initial load
duke
parents:
diff changeset
   205
            throw new javax.xml.transform.TransformerException ( e );
7f561c08de6b Initial load
duke
parents:
diff changeset
   206
        }
7f561c08de6b Initial load
duke
parents:
diff changeset
   207
    }
7f561c08de6b Initial load
duke
parents:
diff changeset
   208
7f561c08de6b Initial load
duke
parents:
diff changeset
   209
}