Source Code Cross Referenced for JavaServiceDesc.java in  » Portal » stringbeans-3.5 » com » nabhinc » ws » soap » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Portal » stringbeans 3.5 » com.nabhinc.ws.soap 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 2001-2004 The Apache Software Foundation.
0003:         *
0004:         * Licensed under the Apache License, Version 2.0 (the "License");
0005:         * you may not use this file except in compliance with the License.
0006:         * You may obtain a copy of the License at
0007:         *
0008:         *      http://www.apache.org/licenses/LICENSE-2.0
0009:         *
0010:         * Unless required by applicable law or agreed to in writing, software
0011:         * distributed under the License is distributed on an "AS IS" BASIS,
0012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013:         * See the License for the specific language governing permissions and
0014:         * limitations under the License.
0015:         */
0016:
0017:        /*
0018:         * Modified by Nabh Information Systems, Inc. for Stringbeans Web Services
0019:         * Framework.
0020:         * 
0021:         * Modifications (c) 2005 Nabh Information Systems, Inc.
0022:         */
0023:        package com.nabhinc.ws.soap;
0024:
0025:        import org.apache.axis.AxisServiceConfig;
0026:        import org.apache.axis.Constants;
0027:        import org.apache.axis.InternalException;
0028:        import org.apache.axis.AxisProperties;
0029:        import org.apache.axis.components.logger.LogFactory;
0030:        import org.apache.axis.encoding.*;
0031:        import org.apache.axis.constants.Style;
0032:        import org.apache.axis.constants.Use;
0033:        import org.apache.axis.description.FaultDesc;
0034:        import org.apache.axis.description.OperationDesc;
0035:        import org.apache.axis.description.ParameterDesc;
0036:        import org.apache.axis.description.ServiceDesc;
0037:        import org.apache.axis.message.SOAPBodyElement;
0038:        import org.apache.axis.message.SOAPEnvelope;
0039:        import org.apache.axis.utils.JavaUtils;
0040:        import org.apache.axis.utils.Messages;
0041:        import org.apache.axis.utils.bytecode.ParamNameExtractor;
0042:        import org.apache.axis.wsdl.Skeleton;
0043:        import org.apache.axis.wsdl.fromJava.Namespaces;
0044:        import org.apache.commons.logging.Log;
0045:        import org.w3c.dom.Document;
0046:        import org.w3c.dom.Element;
0047:
0048:        import com.nabhinc.ws.core.PropertyInfo;
0049:        import com.nabhinc.ws.server.RequestInfo;
0050:        import com.nabhinc.ws.server.ServerObjectConfig;
0051:        import com.nabhinc.ws.server.WebService;
0052:
0053:        import javax.xml.namespace.QName;
0054:        import javax.xml.rpc.holders.Holder;
0055:        import java.lang.reflect.InvocationTargetException;
0056:        import java.lang.reflect.Method;
0057:        import java.lang.reflect.Modifier;
0058:        import java.util.ArrayList;
0059:        import java.util.Collection;
0060:        import java.util.Collections;
0061:        import java.util.Comparator;
0062:        import java.util.HashMap;
0063:        import java.util.Iterator;
0064:        import java.util.List;
0065:        import java.util.StringTokenizer;
0066:
0067:        /**
0068:         * A ServiceDesc is an abstract description of a service.
0069:         *
0070:         * ServiceDescs contain OperationDescs, which are descriptions of operations.
0071:         * The information about a service's operations comes from one of two places:
0072:         * 1) deployment, or 2) introspection.
0073:         *
0074:         * @author Glen Daniels (gdaniels@apache.org)
0075:         */
0076:        public class JavaServiceDesc implements  ServiceDesc {
0077:            /**
0078:             * Comment for <code>serialVersionUID</code>
0079:             */
0080:            private static final long serialVersionUID = 3256445789579456566L;
0081:
0082:            protected static Log log = LogFactory.getLog(JavaServiceDesc.class
0083:                    .getName());
0084:
0085:            /** The name of this service */
0086:            private String name = null;
0087:
0088:            /** The documentation of this service */
0089:            private String documentation = null;
0090:
0091:            /** Style/Use */
0092:            private Style style = Style.RPC;
0093:            private Use use = Use.ENCODED;
0094:
0095:            // Style and Use are related.  By default, if Style==RPC, Use should be
0096:            // ENCODED.  But if Style==DOCUMENT, Use should be LITERAL.  So we want
0097:            // to keep the defaults synced until someone explicitly sets the Use.
0098:            private boolean useSet = false;
0099:
0100:            /** Our operations - a list of OperationDescs */
0101:            private ArrayList operations = new ArrayList();
0102:
0103:            /** A collection of namespaces which will map to this service */
0104:            private List namespaceMappings = null;
0105:
0106:            /**
0107:             * Where does our WSDL document live?  If this is non-null, the "?WSDL"
0108:             * generation will automatically return this file instead of dynamically
0109:             * creating a WSDL.  BE CAREFUL because this means that Handlers will
0110:             * not be able to add to the WSDL for extensions/headers....
0111:             */
0112:            private String wsdlFileName = null;
0113:
0114:            /**
0115:             * An endpoint URL which someone has specified for this service.  If
0116:             * this is set, WSDL generation will pick it up instead of defaulting
0117:             * to the transport URL.
0118:             */
0119:            private String endpointURL = null;
0120:
0121:            /** Place to store user-extensible service-related properties */
0122:            private HashMap properties = null;
0123:
0124:            /** Lookup caches */
0125:            private HashMap name2OperationsMap = null;
0126:            private HashMap qname2OperationsMap = null;
0127:            private transient HashMap method2OperationMap = new HashMap();
0128:
0129:            // THE FOLLOWING STUFF IS ALL JAVA-SPECIFIC, AND WILL BE FACTORED INTO
0130:            // A JAVA-SPECIFIC SUBCLASS.  --Glen
0131:
0132:            /** List of allowed methods */
0133:            /** null allows everything, an empty ArrayList allows nothing */
0134:            private List allowedMethods = null;
0135:
0136:            /** List if disallowed methods */
0137:            private List disallowedMethods = null;
0138:
0139:            /** Implementation class */
0140:            private Class implClass = null;
0141:
0142:            /**
0143:             * Is the implementation a Skeleton?  If this is true, it will generate
0144:             * a Fault to provide OperationDescs via WSDD.
0145:             */
0146:            private boolean isSkeletonClass = false;
0147:
0148:            /** Cached copy of the skeleton "getOperationDescByName" method */
0149:            private transient Method skelMethod = null;
0150:
0151:            /** Classes at which we should stop looking up the inheritance chain
0152:             *  when introspecting
0153:             */
0154:            private ArrayList stopClasses = null;
0155:
0156:            /** Lookup caches */
0157:            private transient HashMap method2ParamsMap = new HashMap();
0158:            private OperationDesc messageServiceDefaultOp = null;
0159:
0160:            /** Method names for which we have completed any introspection necessary */
0161:            private ArrayList completedNames = new ArrayList();
0162:
0163:            /** Our typemapping for resolving Java<->XML type issues */
0164:            private TypeMapping tm = null;
0165:            private TypeMappingRegistry tmr = null;
0166:
0167:            private boolean haveAllSkeletonMethods = false;
0168:            private boolean introspectionComplete = false;
0169:
0170:            /**
0171:             * Default constructor
0172:             */
0173:            public JavaServiceDesc() {
0174:            }
0175:
0176:            /**
0177:             * What kind of service is this?
0178:             * @return
0179:             */
0180:            public Style getStyle() {
0181:                return style;
0182:            }
0183:
0184:            public void setStyle(Style style) {
0185:                this .style = style;
0186:                if (!useSet) {
0187:                    // Use hasn't been explicitly set, so track style
0188:                    use = style == Style.RPC ? Use.ENCODED : Use.LITERAL;
0189:                }
0190:            }
0191:
0192:            /**
0193:             * What kind of use is this?
0194:             * @return
0195:             */
0196:            public Use getUse() {
0197:                return use;
0198:            }
0199:
0200:            public void setUse(Use use) {
0201:                useSet = true;
0202:                this .use = use;
0203:            }
0204:
0205:            /**
0206:             * Determine whether or not this is a "wrapped" invocation, i.e. whether
0207:             * the outermost XML element of the "main" body element represents a
0208:             * method call, with the immediate children of that element representing
0209:             * arguments to the method.
0210:             *
0211:             * @return true if this is wrapped (i.e. RPC or WRAPPED style),
0212:             *         false otherwise
0213:             */
0214:            public boolean isWrapped() {
0215:                return ((style == Style.RPC) || (style == Style.WRAPPED));
0216:            }
0217:
0218:            /**
0219:             * the wsdl file of the service.
0220:             * When null, it means that the wsdl should be autogenerated
0221:             * @return filename or null
0222:             */
0223:            public String getWSDLFile() {
0224:                return wsdlFileName;
0225:            }
0226:
0227:            /**
0228:             * set the wsdl file of the service; this causes the named
0229:             * file to be returned on a ?wsdl, probe, not introspection
0230:             * generated wsdl.
0231:             * @param wsdlFileName filename or null to re-enable introspection
0232:             */
0233:            public void setWSDLFile(String wsdlFileName) {
0234:                this .wsdlFileName = wsdlFileName;
0235:            }
0236:
0237:            public List getAllowedMethods() {
0238:                return allowedMethods;
0239:            }
0240:
0241:            public void setAllowedMethods(List allowedMethods) {
0242:                this .allowedMethods = allowedMethods;
0243:            }
0244:
0245:            public Class getImplClass() {
0246:                return implClass;
0247:            }
0248:
0249:            /**
0250:             * set the implementation class
0251:             * <p>
0252:             * Warning: You cannot call getInitializedServiceDesc() after setting this
0253:             * as it uses this to indicate its work has already been done.
0254:             *
0255:             * @param implClass
0256:             * @throws IllegalArgumentException if the implementation class is already
0257:             *         set
0258:             */
0259:            public void setImplClass(Class implClass) {
0260:                if (this .implClass != null)
0261:                    throw new IllegalArgumentException(Messages
0262:                            .getMessage("implAlreadySet"));
0263:
0264:                this .implClass = implClass;
0265:                if (Skeleton.class.isAssignableFrom(implClass)) {
0266:                    isSkeletonClass = true;
0267:                    loadSkeletonOperations();
0268:                }
0269:            }
0270:
0271:            private void loadSkeletonOperations() {
0272:                Method method = null;
0273:                try {
0274:                    method = implClass.getDeclaredMethod("getOperationDescs",
0275:                            new Class[] {});
0276:                } catch (NoSuchMethodException e) {
0277:                } catch (SecurityException e) {
0278:                }
0279:                if (method == null) {
0280:                    // FIXME : Throw an error?
0281:                    return;
0282:                }
0283:
0284:                try {
0285:                    Collection opers = (Collection) method.invoke(implClass,
0286:                            (Object[]) null);
0287:                    for (Iterator i = opers.iterator(); i.hasNext();) {
0288:                        OperationDesc skelDesc = (OperationDesc) i.next();
0289:                        addOperationDesc(skelDesc);
0290:                    }
0291:                } catch (IllegalAccessException e) {
0292:                    if (log.isDebugEnabled()) {
0293:                        log.debug(Messages.getMessage("exception00"), e);
0294:                    }
0295:                    return;
0296:                } catch (IllegalArgumentException e) {
0297:                    if (log.isDebugEnabled()) {
0298:                        log.debug(Messages.getMessage("exception00"), e);
0299:                    }
0300:                    return;
0301:                } catch (InvocationTargetException e) {
0302:                    if (log.isDebugEnabled()) {
0303:                        log.debug(Messages.getMessage("exception00"), e);
0304:                    }
0305:                    return;
0306:                }
0307:                haveAllSkeletonMethods = true;
0308:            }
0309:
0310:            public TypeMapping getTypeMapping() {
0311:                if (tm == null) {
0312:                    return DefaultTypeMappingImpl.getSingletonDelegate();
0313:                    //            throw new RuntimeException(Messages.getMessage("noDefaultTypeMapping00"));
0314:                }
0315:                return tm;
0316:            }
0317:
0318:            public void setTypeMapping(TypeMapping tm) {
0319:                this .tm = tm;
0320:            }
0321:
0322:            /**
0323:             * the name of the service
0324:             */
0325:            public String getName() {
0326:                return name;
0327:            }
0328:
0329:            /**
0330:             * the name of the service
0331:             * @param name
0332:             */
0333:            public void setName(String name) {
0334:                this .name = name;
0335:            }
0336:
0337:            /**
0338:             * get the documentation for the service
0339:             */
0340:            public String getDocumentation() {
0341:                return documentation;
0342:            }
0343:
0344:            /**
0345:             * set the documentation for the service
0346:             */
0347:            public void setDocumentation(String documentation) {
0348:                this .documentation = documentation;
0349:            }
0350:
0351:            public ArrayList getStopClasses() {
0352:                return stopClasses;
0353:            }
0354:
0355:            public void setStopClasses(ArrayList stopClasses) {
0356:                this .stopClasses = stopClasses;
0357:            }
0358:
0359:            public List getDisallowedMethods() {
0360:                return disallowedMethods;
0361:            }
0362:
0363:            public void setDisallowedMethods(List disallowedMethods) {
0364:                this .disallowedMethods = disallowedMethods;
0365:            }
0366:
0367:            public void removeOperationDesc(OperationDesc operation) {
0368:                operations.remove(operation);
0369:                operation.setParent(null);
0370:
0371:                if (name2OperationsMap != null) {
0372:                    String name = operation.getName();
0373:                    ArrayList overloads = (ArrayList) name2OperationsMap
0374:                            .get(name);
0375:                    if (overloads != null) {
0376:                        overloads.remove(operation);
0377:                        if (overloads.size() == 0) {
0378:                            name2OperationsMap.remove(name);
0379:                        }
0380:                    }
0381:                }
0382:
0383:                if (qname2OperationsMap != null) {
0384:                    QName qname = operation.getElementQName();
0385:                    ArrayList list = (ArrayList) qname2OperationsMap.get(qname);
0386:                    if (list != null) {
0387:                        list.remove(operation);
0388:                    }
0389:                }
0390:
0391:                if (method2OperationMap != null) {
0392:                    Method method = operation.getMethod();
0393:                    if (method != null) {
0394:                        method2OperationMap.remove(method);
0395:                    }
0396:                }
0397:            }
0398:
0399:            public void addOperationDesc(OperationDesc operation) {
0400:                operations.add(operation);
0401:                operation.setParent(this );
0402:                if (name2OperationsMap == null) {
0403:                    name2OperationsMap = new HashMap();
0404:                }
0405:
0406:                // Add name to name2Operations Map
0407:                String name = operation.getName();
0408:                ArrayList overloads = (ArrayList) name2OperationsMap.get(name);
0409:                if (overloads == null) {
0410:                    overloads = new ArrayList();
0411:                    name2OperationsMap.put(name, overloads);
0412:                } else if (JavaUtils.isTrue(AxisProperties
0413:                        .getProperty(Constants.WSIBP11_COMPAT_PROPERTY))
0414:                        && overloads.size() > 0) {
0415:                    throw new RuntimeException(Messages.getMessage(
0416:                            "noOverloadedOperations", name));
0417:                }
0418:                overloads.add(operation);
0419:            }
0420:
0421:            /**
0422:             * get all the operations as a list of OperationDescs.
0423:             * this method triggers an evaluation of the valid operations by
0424:             * introspection, so use sparingly
0425:             * @return reference to the operations array. This is not a copy
0426:             */
0427:            public ArrayList getOperations() {
0428:                loadServiceDescByIntrospection(); // Just in case...
0429:                return operations;
0430:            }
0431:
0432:            /**
0433:             * get all overloaded operations by name
0434:             * @param methodName
0435:             * @return null for no match, or an array of OperationDesc objects
0436:             */
0437:            public OperationDesc[] getOperationsByName(String methodName) {
0438:                getSyncedOperationsForName(implClass, methodName);
0439:
0440:                if (name2OperationsMap == null)
0441:                    return null;
0442:
0443:                ArrayList overloads = (ArrayList) name2OperationsMap
0444:                        .get(methodName);
0445:                if (overloads == null) {
0446:                    return null;
0447:                }
0448:
0449:                OperationDesc[] array = new OperationDesc[overloads.size()];
0450:                return (OperationDesc[]) overloads.toArray(array);
0451:            }
0452:
0453:            /**
0454:             * Return an operation matching the given method name.  Note that if we
0455:             * have multiple overloads for this method, we will return the first one.
0456:             * @return null for no match
0457:             */
0458:            public OperationDesc getOperationByName(String methodName) {
0459:                // If we need to load up operations from introspection data, do it.
0460:                // This returns fast if we don't need to do anything, so it's not very
0461:                // expensive.
0462:                getSyncedOperationsForName(implClass, methodName);
0463:
0464:                if (name2OperationsMap == null)
0465:                    return null;
0466:
0467:                ArrayList overloads = (ArrayList) name2OperationsMap
0468:                        .get(methodName);
0469:                if (overloads == null) {
0470:                    return null;
0471:                }
0472:
0473:                return (OperationDesc) overloads.get(0);
0474:            }
0475:
0476:            /**
0477:             * Map an XML QName to an operation.  Returns the first one it finds
0478:             * in the case of mulitple matches.
0479:             * @return null for no match
0480:             */
0481:            public OperationDesc getOperationByElementQName(QName qname) {
0482:                OperationDesc[] overloads = getOperationsByQName(qname);
0483:
0484:                // Return the first one....
0485:                if ((overloads != null) && overloads.length > 0)
0486:                    return overloads[0];
0487:
0488:                return null;
0489:            }
0490:
0491:            /**
0492:             * Return all operations which match this QName (i.e. get all the
0493:             * overloads)
0494:             * @return null for no match
0495:             */
0496:            public OperationDesc[] getOperationsByQName(QName qname) {
0497:                // Look in our mapping of QNames -> operations.
0498:
0499:                // But first, let's make sure we've initialized said mapping....
0500:                initQNameMap();
0501:
0502:                ArrayList overloads = (ArrayList) qname2OperationsMap
0503:                        .get(qname);
0504:                if (overloads == null) {
0505:                    // Nothing specifically matching this QName.
0506:                    if (name2OperationsMap != null) {
0507:                        if ((isWrapped() || ((style == Style.MESSAGE) && (getDefaultNamespace() == null)))) {
0508:                            // Try ignoring the namespace....?
0509:                            overloads = (ArrayList) name2OperationsMap
0510:                                    .get(qname.getLocalPart());
0511:                        } else {
0512:                            // TODO the above code is weird: a JavaServiceDesc can  be document or rpc and
0513:                            // still define a WSDL operation using a wrapper style  mapping.
0514:                            // The following code handles this case.
0515:                            Object ops = name2OperationsMap.get(qname
0516:                                    .getLocalPart());
0517:                            if (ops != null) {
0518:                                overloads = new ArrayList((Collection) ops);
0519:                                for (Iterator iter = overloads.iterator(); iter
0520:                                        .hasNext();) {
0521:                                    OperationDesc operationDesc = (OperationDesc) iter
0522:                                            .next();
0523:                                    if (Style.WRAPPED != operationDesc
0524:                                            .getStyle()) {
0525:                                        iter.remove();
0526:                                    }
0527:                                }
0528:                            }
0529:                        }
0530:                    }
0531:                    // Handle the case where a single Message-style operation wants
0532:                    // to accept anything.
0533:                    if ((style == Style.MESSAGE)
0534:                            && (messageServiceDefaultOp != null))
0535:                        return new OperationDesc[] { messageServiceDefaultOp };
0536:
0537:                    if (overloads == null)
0538:                        return null;
0539:                }
0540:
0541:                getSyncedOperationsForName(implClass,
0542:                        ((OperationDesc) overloads.get(0)).getName());
0543:
0544:                // Sort the overloads by number of arguments - prevents us calling methods
0545:                // with more parameters than supplied in the request (with missing parameters
0546:                // defaulted to null) when a perfectly good method exists with exactly the
0547:                // supplied parameters.
0548:                Collections.sort(overloads, new Comparator() {
0549:                    public int compare(Object o1, Object o2) {
0550:                        Method meth1 = ((OperationDesc) o1).getMethod();
0551:                        Method meth2 = ((OperationDesc) o2).getMethod();
0552:                        return (meth1.getParameterTypes().length - meth2
0553:                                .getParameterTypes().length);
0554:                    }
0555:                });
0556:
0557:                OperationDesc[] array = new OperationDesc[overloads.size()];
0558:                return (OperationDesc[]) overloads.toArray(array);
0559:            }
0560:
0561:            private synchronized void initQNameMap() {
0562:                if (qname2OperationsMap == null) {
0563:                    loadServiceDescByIntrospection();
0564:
0565:                    qname2OperationsMap = new HashMap();
0566:                    for (Iterator i = operations.iterator(); i.hasNext();) {
0567:                        OperationDesc operationDesc = (OperationDesc) i.next();
0568:                        QName qname = operationDesc.getElementQName();
0569:                        ArrayList list = (ArrayList) qname2OperationsMap
0570:                                .get(qname);
0571:                        if (list == null) {
0572:                            list = new ArrayList();
0573:                            qname2OperationsMap.put(qname, list);
0574:                        }
0575:                        list.add(operationDesc);
0576:                    }
0577:                }
0578:            }
0579:
0580:            /**
0581:             * Synchronize an existing OperationDesc to a java.lang.Method.
0582:             *
0583:             * This method is used when the deployer has specified operation metadata
0584:             * and we want to match that up with a real java Method so that the
0585:             * Operation-level dispatch carries us all the way to the implementation.
0586:             * Search the declared methods on the implementation class to find one
0587:             * with an argument list which matches our parameter list.
0588:             */
0589:            private void syncOperationToClass(OperationDesc oper,
0590:                    Class implClass) {
0591:                // ------------------------------------------------
0592:                // Developer Note:
0593:                //
0594:                // The goal of the sync code is to associate
0595:                // the OperationDesc/ParamterDesc with the
0596:                // target Method.  There are a number of ways to get to this
0597:                // point depending on what information
0598:                // is available.  Here are the main scenarios:
0599:                //
0600:                // A) Deployment with wsdd (non-skeleton):
0601:                //   * OperationDesc/ParameterDesc loaded from deploy.wsdd
0602:                //   * Loaded ParameterDesc does not have javaType,
0603:                //     so it is discovered using the TypeMappingRegistry
0604:                //     (also loaded via deploy.wsdd) and the
0605:                //     typeQName specified by the ParameterDesc.
0606:                //   * Sync occurs using the discovered
0607:                //     javaTypes and the javaTypes of the Method
0608:                //     parameters
0609:                //
0610:                // B) Deployment with no wsdd OperationDesc info (non-skeleton):
0611:                //   * Implementation Class introspected to build
0612:                //     OperationDesc/ParameterDesc.
0613:                //   * ParameterDesc is known via introspection.
0614:                //   * ParameterDesc are discovered using javaType
0615:                //     and TypeMappingRegistry.
0616:                //   * Sync occurs using the introspected
0617:                //     javaTypes and the javaTypes of the Method
0618:                //     parameters
0619:                //
0620:                // C) Deployment with wsdd (skeleton):
0621:                //   * OperationDesc/ParameterDesc loaded from the Skeleton
0622:                //   * In this scenario the ParameterDescs' already
0623:                //     have javaTypes (see E below).
0624:                //   * Sync occurs using the ParameterDesc
0625:                //     javaTypes and the javaTypes of the Method
0626:                //     parameters.
0627:                //
0628:                // D) Commandline Java2WSDL loading non-Skeleton Class/Interface
0629:                //   * Class/Interface introspected to build
0630:                //     OperationDesc/ParameterDesc.
0631:                //   * The javaTypes of the ParameterDesc are set using introspection.
0632:                //   * typeQNames are determined for built-in types using
0633:                //     from the default TypeMappingRegistry.  Other
0634:                //     typeQNames are guessed from the javaType.  Note
0635:                //     that there is no loaded TypeMappingRegistry.
0636:                //   * Sync occurs using the ParameterDesc
0637:                //     javaTypes and the javaTypes of the Method
0638:                //     parameters.
0639:                //
0640:                // E) Commandline Java2WSDL loading Skeleton Class
0641:                //   * OperationDesc/ParameterDesc loaded from Skeleton
0642:                //   * Each ParameterDesc has an appropriate typeQName
0643:                //   * Each ParameterDesc also has a javaType, which is
0644:                //     essential for sync'ing up with the
0645:                //     method since there is no loaded TypeMappingRegistry.
0646:                //   * Syncronization occurs using the ParameterDesc
0647:                //     javaTypes and the javaTypes of the Method
0648:                //     parameters.
0649:                //
0650:                // So in each scenario, the ultimate sync'ing occurs
0651:                // using the javaTypes of the ParameterDescs and the
0652:                // javaTypes of the Method parameters.
0653:                //
0654:                // ------------------------------------------------
0655:
0656:                // If we're already mapped to a Java method, no need to do anything.
0657:                if (oper.getMethod() != null)
0658:                    return;
0659:
0660:                // Find the method.  We do this once for each Operation.
0661:
0662:                Method[] methods = getMethods(implClass);
0663:                // A place to keep track of possible matches
0664:                Method possibleMatch = null;
0665:
0666:                for (int i = 0; i < methods.length; i++) {
0667:                    Method method = methods[i];
0668:                    if (Modifier.isPublic(method.getModifiers())
0669:                            && method.getName().equals(oper.getName())
0670:                            && method2OperationMap.get(method) == null) {
0671:
0672:                        if (style == Style.MESSAGE) {
0673:                            int messageOperType = checkMessageMethod(method);
0674:                            if (messageOperType == OperationDesc.MSG_METHOD_NONCONFORMING)
0675:                                continue;
0676:                            if (messageOperType == -1) {
0677:                                throw new InternalException(
0678:                                        "Couldn't match method to any of the allowable message-style patterns!");
0679:                            }
0680:                            oper.setMessageOperationStyle(messageOperType);
0681:
0682:                            // Don't bother checking params if we're message style
0683:                            possibleMatch = method;
0684:                            break;
0685:                        }
0686:
0687:                        // Check params
0688:                        Class[] paramTypes = method.getParameterTypes();
0689:                        if (paramTypes.length != oper.getNumParams())
0690:                            continue;
0691:
0692:                        int j;
0693:                        boolean conversionNecessary = false;
0694:                        for (j = 0; j < paramTypes.length; j++) {
0695:                            Class type = paramTypes[j];
0696:                            Class actualType = type;
0697:                            if (Holder.class.isAssignableFrom(type)) {
0698:                                actualType = JavaUtils.getHolderValueType(type);
0699:                            }
0700:                            ParameterDesc param = oper.getParameter(j);
0701:                            QName typeQName = param.getTypeQName();
0702:                            if (typeQName == null) {
0703:                                // No typeQName is available.  Set it using
0704:                                // information from the actual type.
0705:                                // (Scenarios B and D)
0706:                                // There is no need to try and match with
0707:                                // the Method parameter javaType because
0708:                                // the ParameterDesc is being constructed
0709:                                // by introspecting the Method.
0710:                                typeQName = getTypeMapping().getTypeQName(
0711:                                        actualType);
0712:                                param.setTypeQName(typeQName);
0713:                            } else {
0714:                                // A type qname is available.
0715:                                // Ensure that the ParameterDesc javaType
0716:                                // is convertable to the Method parameter type
0717:                                //
0718:                                // Use the available javaType (Scenarios C and E)
0719:                                // or get one from the TMR (Scenario A).
0720:                                Class paramClass = param.getJavaType();
0721:                                if (paramClass != null
0722:                                        && JavaUtils
0723:                                                .getHolderValueType(paramClass) != null) {
0724:                                    paramClass = JavaUtils
0725:                                            .getHolderValueType(paramClass);
0726:                                }
0727:                                if (paramClass == null) {
0728:                                    paramClass = getTypeMapping()
0729:                                            .getClassForQName(
0730:                                                    param.getTypeQName(), type);
0731:                                }
0732:
0733:                                if (paramClass != null) {
0734:                                    // This is a match if the paramClass is somehow
0735:                                    // convertable to the "real" parameter type.  If not,
0736:                                    // break out of this loop.
0737:                                    if (!JavaUtils.isConvertable(paramClass,
0738:                                            actualType)) {
0739:                                        break;
0740:                                    }
0741:
0742:                                    if (!actualType
0743:                                            .isAssignableFrom(paramClass)) {
0744:                                        // This doesn't fit without conversion
0745:                                        conversionNecessary = true;
0746:                                    }
0747:                                }
0748:                            }
0749:                            // In all scenarios the ParameterDesc javaType is set to
0750:                            // match the javaType in the corresponding parameter.
0751:                            // This is essential.
0752:                            param.setJavaType(type);
0753:                        }
0754:
0755:                        if (j != paramTypes.length) {
0756:                            // failed.
0757:                            continue;
0758:                        }
0759:
0760:                        // This is our latest possibility
0761:                        possibleMatch = method;
0762:
0763:                        // If this is exactly it, stop now.  Otherwise keep looking
0764:                        // just in case we find a better match.
0765:                        if (!conversionNecessary) {
0766:                            break;
0767:                        }
0768:
0769:                    }
0770:                }
0771:
0772:                // At this point, we may or may not have a possible match.
0773:                // FIXME : Should we prefer an exact match from a base class over
0774:                //         a with-conversion match from the target class?  If so,
0775:                //         we'll need to change the logic below.
0776:                if (possibleMatch != null) {
0777:                    Class returnClass = possibleMatch.getReturnType();
0778:                    oper.setReturnClass(returnClass);
0779:
0780:                    QName returnType = oper.getReturnType();
0781:                    if (returnType == null) {
0782:                        oper.setReturnType(getTypeMapping().getTypeQName(
0783:                                returnClass));
0784:                    }
0785:
0786:                    // Do the faults
0787:                    createFaultMetadata(possibleMatch, oper);
0788:
0789:                    oper.setMethod(possibleMatch);
0790:                    method2OperationMap.put(possibleMatch, oper);
0791:                    return;
0792:                }
0793:
0794:                // Didn't find a match.  Try the superclass, if appropriate
0795:                Class super Class = implClass.getSuperclass();
0796:                if (super Class != null
0797:                        && !super Class.getName().startsWith("java.")
0798:                        && !super Class.getName().startsWith("javax.")
0799:                        && (stopClasses == null || !stopClasses
0800:                                .contains(super Class.getName()))) {
0801:                    syncOperationToClass(oper, super Class);
0802:                }
0803:
0804:                // Exception if sync fails to find method for operation
0805:                if (oper.getMethod() == null) {
0806:                    InternalException ie = new InternalException(Messages
0807:                            .getMessage("serviceDescOperSync00",
0808:                                    oper.getName(), implClass.getName()));
0809:                    throw ie;
0810:                }
0811:            }
0812:
0813:            private Method[] getMethods(Class implClass) {
0814:                if (implClass.isInterface()) {
0815:                    // Returns all methods incl inherited
0816:                    return implClass.getMethods();
0817:                } else {
0818:                    return implClass.getDeclaredMethods();
0819:                }
0820:            }
0821:
0822:            private int checkMessageMethod(Method method) {
0823:                // Collect the types so we know what we're dealing with in the target
0824:                // method.
0825:                Class[] params = method.getParameterTypes();
0826:
0827:                if (params.length == 1) {
0828:                    if ((params[0] == Element[].class)
0829:                            && (method.getReturnType() == Element[].class)) {
0830:                        return OperationDesc.MSG_METHOD_ELEMENTARRAY;
0831:                    }
0832:
0833:                    if ((params[0] == SOAPBodyElement[].class)
0834:                            && (method.getReturnType() == SOAPBodyElement[].class)) {
0835:                        return OperationDesc.MSG_METHOD_BODYARRAY;
0836:                    }
0837:
0838:                    if ((params[0] == Document.class)
0839:                            && (method.getReturnType() == Document.class)) {
0840:                        return OperationDesc.MSG_METHOD_DOCUMENT;
0841:                    }
0842:                } else if (params.length == 2) {
0843:                    if (((params[0] == SOAPEnvelope.class) && (params[1] == SOAPEnvelope.class))
0844:                            || ((params[0] == javax.xml.soap.SOAPEnvelope.class) && (params[1] == javax.xml.soap.SOAPEnvelope.class))
0845:                            && (method.getReturnType() == void.class)) {
0846:                        return OperationDesc.MSG_METHOD_SOAPENVELOPE;
0847:                    }
0848:                }
0849:                if (null != allowedMethods && !allowedMethods.isEmpty())
0850:                    throw new InternalException(Messages.getMessage(
0851:                            "badMsgMethodParams", method.getName()));
0852:                return OperationDesc.MSG_METHOD_NONCONFORMING;
0853:            }
0854:
0855:            /**
0856:             * Fill in a service description by introspecting the implementation
0857:             * class.
0858:             */
0859:            public void loadServiceDescByIntrospection() {
0860:                loadServiceDescByIntrospection(implClass);
0861:
0862:                // Setting this to null means there is nothing more to do, and it
0863:                // avoids future string compares.
0864:                completedNames = null;
0865:            }
0866:
0867:            /**
0868:             * Fill in a service description by introspecting the implementation
0869:             * class.
0870:             */
0871:            public void loadServiceDescByIntrospection(Class implClass) {
0872:                if (introspectionComplete || implClass == null) {
0873:                    return;
0874:                }
0875:
0876:                // set the implementation class for the service description
0877:                this .implClass = implClass;
0878:                if (Skeleton.class.isAssignableFrom(implClass)) {
0879:                    isSkeletonClass = true;
0880:                    loadSkeletonOperations();
0881:                }
0882:
0883:                /** If the class knows what it should be exporting,
0884:                 * respect its wishes.
0885:                 */
0886:                AxisServiceConfig axisConfig = null;
0887:                try {
0888:                    Method method = implClass.getDeclaredMethod(
0889:                            "getAxisServiceConfig", new Class[] {});
0890:                    if (method != null
0891:                            && Modifier.isStatic(method.getModifiers())) {
0892:                        axisConfig = (AxisServiceConfig) method.invoke(null,
0893:                                (Object[]) null);
0894:                    }
0895:                } catch (Exception e) {
0896:                    // No problem, just continue without...
0897:                }
0898:
0899:                if (axisConfig != null) {
0900:                    String allowedMethodsStr = axisConfig.getAllowedMethods();
0901:                    if (allowedMethodsStr != null
0902:                            && !"*".equals(allowedMethodsStr)) {
0903:                        ArrayList methodList = new ArrayList();
0904:                        StringTokenizer tokenizer = new StringTokenizer(
0905:                                allowedMethodsStr, " ,");
0906:                        while (tokenizer.hasMoreTokens()) {
0907:                            methodList.add(tokenizer.nextToken());
0908:                        }
0909:                        setAllowedMethods(methodList);
0910:                    }
0911:                }
0912:
0913:                loadServiceDescByIntrospectionRecursive(implClass);
0914:
0915:                // All operations should now be synchronized.  Check it.
0916:                for (Iterator iterator = operations.iterator(); iterator
0917:                        .hasNext();) {
0918:                    OperationDesc operation = (OperationDesc) iterator.next();
0919:                    if (operation.getMethod() == null) {
0920:                        throw new InternalException(Messages.getMessage(
0921:                                "badWSDDOperation", operation.getName(), ""
0922:                                        + operation.getNumParams()));
0923:                    }
0924:                }
0925:
0926:                if ((style == Style.MESSAGE) && operations.size() == 1) {
0927:                    messageServiceDefaultOp = (OperationDesc) operations.get(0);
0928:                }
0929:
0930:                introspectionComplete = true;
0931:            }
0932:
0933:            /**
0934:             * Is this method from ServiceLifeCycle interface?
0935:             * @param m
0936:             * @return true if this method is from ServiceLifeCycle interface
0937:             */
0938:            private boolean isServiceLifeCycleMethod(Class implClass, Method m) {
0939:                if (WebService.class.isAssignableFrom(implClass)) {
0940:                    String methodName = m.getName();
0941:
0942:                    if (methodName.equals("init")) {
0943:                        // Check if the method signature is 
0944:                        // "public abstract void init(Object context) throws ServiceException;"
0945:                        Class[] classes = m.getParameterTypes();
0946:                        if (classes != null && classes.length == 1
0947:                                && classes[0] == ServerObjectConfig.class
0948:                                && m.getReturnType() == Void.TYPE) {
0949:                            return true;
0950:                        }
0951:                    } else if (methodName.equals("destroy")) {
0952:                        // Check if the method signature is 
0953:                        // "public abstract void destroy();"
0954:                        Class[] classes = m.getParameterTypes();
0955:                        if (classes != null && classes.length == 0
0956:                                && m.getReturnType() == Void.TYPE) {
0957:                            return true;
0958:                        }
0959:                    } else if (methodName.equals("invoke")) {
0960:                        // Check if the method signature is 
0961:                        // "public abstract void init(Object context) throws ServiceException;"
0962:                        Class[] classes = m.getParameterTypes();
0963:                        if (classes != null && classes.length == 1
0964:                                && classes[0] == RequestInfo.class
0965:                                && m.getReturnType() == Object.class) {
0966:                            return true;
0967:                        }
0968:                    } else if (methodName.equals("start")) {
0969:                        // Check if the method signature is 
0970:                        // "public abstract void init(Object context) throws ServiceException;"
0971:                        Class[] classes = m.getParameterTypes();
0972:                        if (classes != null && classes.length == 0) {
0973:                            return true;
0974:                        }
0975:                    } else if (methodName.equals("stop")) {
0976:                        // Check if the method signature is 
0977:                        // "public abstract void init(Object context) throws ServiceException;"
0978:                        Class[] classes = m.getParameterTypes();
0979:                        if (classes != null && classes.length == 0) {
0980:                            return true;
0981:                        }
0982:                    } else if (methodName.equals("setProperties")) {
0983:                        // Check if the method signature is 
0984:                        // "public abstract void init(Object context) throws ServiceException;"
0985:                        Class[] classes = m.getParameterTypes();
0986:                        if (classes != null
0987:                                && classes.length == 1
0988:                                && classes[0].isArray()
0989:                                && classes[0].getComponentType() == PropertyInfo.class
0990:                                && m.getReturnType() == Void.TYPE) {
0991:                            return true;
0992:                        }
0993:                    }
0994:                }
0995:                return false;
0996:            }
0997:
0998:            /**
0999:             * Recursive helper class for loadServiceDescByIntrospection
1000:             */
1001:            private void loadServiceDescByIntrospectionRecursive(Class implClass) {
1002:                if (Skeleton.class.equals(implClass)) {
1003:                    return;
1004:                }
1005:
1006:                Method[] methods = getMethods(implClass);
1007:
1008:                for (int i = 0; i < methods.length; i++) {
1009:                    if (Modifier.isPublic(methods[i].getModifiers())
1010:                            && !isServiceLifeCycleMethod(implClass, methods[i])) {
1011:                        getSyncedOperationsForName(implClass, methods[i]
1012:                                .getName());
1013:                    }
1014:                }
1015:
1016:                if (implClass.isInterface()) {
1017:                    Class[] super Classes = implClass.getInterfaces();
1018:                    for (int i = 0; i < super Classes.length; i++) {
1019:                        Class super Class = super Classes[i];
1020:                        if (!super Class.getName().startsWith("java.")
1021:                                && !super Class.getName().startsWith("javax.")
1022:                                && (stopClasses == null || !stopClasses
1023:                                        .contains(super Class.getName()))) {
1024:                            loadServiceDescByIntrospectionRecursive(super Class);
1025:                        }
1026:                    }
1027:                } else {
1028:                    Class super Class = implClass.getSuperclass();
1029:                    if (super Class != null
1030:                            && !super Class.getName().startsWith("java.")
1031:                            && !super Class.getName().startsWith("javax.")
1032:                            && (stopClasses == null || !stopClasses
1033:                                    .contains(super Class.getName()))) {
1034:                        loadServiceDescByIntrospectionRecursive(super Class);
1035:                    }
1036:                }
1037:            }
1038:
1039:            /**
1040:             * Fill in a service description by introspecting the implementation
1041:             * class.  This version takes the implementation class and the in-scope
1042:             * TypeMapping.
1043:             */
1044:            public void loadServiceDescByIntrospection(Class cls, TypeMapping tm) {
1045:                // Should we complain if the implClass changes???
1046:                implClass = cls;
1047:                this .tm = tm;
1048:
1049:                if (Skeleton.class.isAssignableFrom(implClass)) {
1050:                    isSkeletonClass = true;
1051:                    loadSkeletonOperations();
1052:                }
1053:
1054:                loadServiceDescByIntrospection();
1055:            }
1056:
1057:            /**
1058:             * Makes sure we have completely synchronized OperationDescs with
1059:             * the implementation class.
1060:             */
1061:            private void getSyncedOperationsForName(Class implClass,
1062:                    String methodName) {
1063:                // If we're a Skeleton deployment, skip the statics.
1064:                if (isSkeletonClass) {
1065:                    if (methodName.equals("getOperationDescByName")
1066:                            || methodName.equals("getOperationDescs"))
1067:                        return;
1068:                }
1069:
1070:                // If we have no implementation class, don't worry about it (we're
1071:                // probably on the client)
1072:                if (implClass == null)
1073:                    return;
1074:
1075:                // If we're done introspecting, or have completed this method, return
1076:                if (completedNames == null
1077:                        || completedNames.contains(methodName))
1078:                    return;
1079:
1080:                // Skip it if it's not a sanctioned method name
1081:                if ((allowedMethods != null)
1082:                        && !allowedMethods.contains(methodName))
1083:                    return;
1084:
1085:                if ((disallowedMethods != null)
1086:                        && disallowedMethods.contains(methodName))
1087:                    return;
1088:
1089:                // If we're a skeleton class, make sure we don't already have any
1090:                // OperationDescs for this name (as that might cause conflicts),
1091:                // then load them up from the Skeleton class.
1092:                if (isSkeletonClass && !haveAllSkeletonMethods) {
1093:                    // FIXME : Check for existing ones and fault if found
1094:
1095:                    if (skelMethod == null) {
1096:                        // Grab metadata from the Skeleton for parameter info
1097:                        try {
1098:                            skelMethod = implClass.getDeclaredMethod(
1099:                                    "getOperationDescByName",
1100:                                    new Class[] { String.class });
1101:                        } catch (NoSuchMethodException e) {
1102:                        } catch (SecurityException e) {
1103:                        }
1104:                        if (skelMethod == null) {
1105:                            // FIXME : Throw an error?
1106:                            return;
1107:                        }
1108:                    }
1109:                    try {
1110:                        List skelList = (List) skelMethod.invoke(implClass,
1111:                                new Object[] { methodName });
1112:                        if (skelList != null) {
1113:                            Iterator i = skelList.iterator();
1114:                            while (i.hasNext()) {
1115:                                addOperationDesc((OperationDesc) i.next());
1116:                            }
1117:                        }
1118:                    } catch (IllegalAccessException e) {
1119:                        if (log.isDebugEnabled()) {
1120:                            log.debug(Messages.getMessage("exception00"), e);
1121:                        }
1122:                        return;
1123:                    } catch (IllegalArgumentException e) {
1124:                        if (log.isDebugEnabled()) {
1125:                            log.debug(Messages.getMessage("exception00"), e);
1126:                        }
1127:                        return;
1128:                    } catch (InvocationTargetException e) {
1129:                        if (log.isDebugEnabled()) {
1130:                            log.debug(Messages.getMessage("exception00"), e);
1131:                        }
1132:                        return;
1133:                    }
1134:                }
1135:
1136:                // OK, go find any current OperationDescs for this method name and
1137:                // make sure they're synced with the actual class.
1138:                if (name2OperationsMap != null) {
1139:                    ArrayList currentOverloads = (ArrayList) name2OperationsMap
1140:                            .get(methodName);
1141:                    if (currentOverloads != null) {
1142:                        // For each one, sync it to the implementation class' methods
1143:                        for (Iterator i = currentOverloads.iterator(); i
1144:                                .hasNext();) {
1145:                            OperationDesc oper = (OperationDesc) i.next();
1146:                            if (oper.getMethod() == null) {
1147:                                syncOperationToClass(oper, implClass);
1148:                            }
1149:                        }
1150:                    }
1151:                }
1152:
1153:                // Now all OperationDescs from deployment data have been completely
1154:                // filled in.  So we now make new OperationDescs for any method
1155:                // overloads which were not covered above.
1156:                // NOTE : This is the "lenient" approach, which allows you to
1157:                // specify one overload and still get the others by introspection.
1158:                // We could equally well return above if we found OperationDescs,
1159:                // and have a rule that if you specify any overloads, you must specify
1160:                // all the ones you want accessible.
1161:
1162:                createOperationsForName(implClass, methodName);
1163:
1164:                // Note that we never have to look at this method name again.
1165:                completedNames.add(methodName);
1166:            }
1167:
1168:            private String getUniqueOperationName(String name) {
1169:                int i = 1;
1170:                String candidate;
1171:                do {
1172:                    candidate = name + i++;
1173:                } while (name2OperationsMap.get(candidate) != null);
1174:
1175:                return candidate;
1176:            }
1177:
1178:            /**
1179:             * Look for methods matching this name, and for each one, create an
1180:             * OperationDesc (if it's not already in our list).
1181:             *
1182:             * TODO: Make this more efficient
1183:             */
1184:            private void createOperationsForName(Class implClass,
1185:                    String methodName) {
1186:                // If we're a Skeleton deployment, skip the statics.
1187:                if (isSkeletonClass) {
1188:                    if (methodName.equals("getOperationDescByName")
1189:                            || methodName.equals("getOperationDescs"))
1190:                        return;
1191:                }
1192:
1193:                Method[] methods = getMethods(implClass);
1194:
1195:                for (int i = 0; i < methods.length; i++) {
1196:                    Method method = methods[i];
1197:                    if (Modifier.isPublic(method.getModifiers())
1198:                            && method.getName().equals(methodName)
1199:                            && !isServiceLifeCycleMethod(implClass, method)) {
1200:                        createOperationForMethod(method);
1201:                    }
1202:                }
1203:
1204:                Class super Class = implClass.getSuperclass();
1205:                if (super Class != null
1206:                        && !super Class.getName().startsWith("java.")
1207:                        && !super Class.getName().startsWith("javax.")
1208:                        && (stopClasses == null || !stopClasses
1209:                                .contains(super Class.getName()))) {
1210:                    createOperationsForName(super Class, methodName);
1211:                }
1212:            }
1213:
1214:            /**
1215:             * Make an OperationDesc from a Java method.
1216:             *
1217:             * In the absence of deployment metadata, this code will introspect a
1218:             * Method and create an appropriate OperationDesc.  If the class
1219:             * implements the Skeleton interface, we will use the metadata from there
1220:             * in constructing the OperationDesc.  If not, we use parameter names
1221:             * from the bytecode debugging info if available, or "in0", "in1", etc.
1222:             * if not.
1223:             */
1224:            private void createOperationForMethod(Method method) {
1225:                // If we've already got it, never mind
1226:                if (method2OperationMap.get(method) != null) {
1227:                    return;
1228:                }
1229:
1230:                Class[] paramTypes = method.getParameterTypes();
1231:
1232:                // And if we've already got an exact match (i.e. an override),
1233:                // never mind
1234:
1235:                ArrayList overloads = name2OperationsMap == null ? null
1236:                        : (ArrayList) name2OperationsMap.get(method.getName());
1237:                if (overloads != null && !overloads.isEmpty()) {
1238:                    // Search each OperationDesc that already has a Method
1239:                    // associated with it, and check for parameter type equivalence.
1240:                    for (int i = 0; i < overloads.size(); i++) {
1241:                        OperationDesc op = (OperationDesc) overloads.get(i);
1242:                        Method checkMethod = op.getMethod();
1243:                        if (checkMethod != null) {
1244:                            Class[] others = checkMethod.getParameterTypes();
1245:                            if (paramTypes.length == others.length) {
1246:                                int j = 0;
1247:                                for (; j < others.length; j++) {
1248:                                    if (!others[j].equals(paramTypes[j]))
1249:                                        break;
1250:                                }
1251:                                // If we got all the way through, we have a match.
1252:                                if (j == others.length)
1253:                                    return;
1254:                            }
1255:                        }
1256:                    }
1257:                }
1258:
1259:                boolean isWSICompliant = JavaUtils.isTrue(AxisProperties
1260:                        .getProperty(Constants.WSIBP11_COMPAT_PROPERTY));
1261:
1262:                // Make an OperationDesc, fill in common stuff
1263:                OperationDesc operation = new OperationDesc();
1264:
1265:                // If we're WS-I compliant, we can't have overloaded operation names.
1266:                // If we find duplicates, we generate unique names for them and map
1267:                // those names to the correct Method.
1268:                String name = method.getName();
1269:                if (isWSICompliant && name2OperationsMap != null) {
1270:                    Collection methodNames = name2OperationsMap.keySet();
1271:                    name = JavaUtils.getUniqueValue(methodNames, name);
1272:                }
1273:                operation.setName(name);
1274:                String defaultNS = "";
1275:                if (namespaceMappings != null && !namespaceMappings.isEmpty()) {
1276:                    // If we have a default namespace mapping, require callers to
1277:                    // use that namespace.
1278:                    defaultNS = (String) namespaceMappings.get(0);
1279:                }
1280:                if (defaultNS.length() == 0) {
1281:                    defaultNS = Namespaces.makeNamespace(method
1282:                            .getDeclaringClass().getName());
1283:                }
1284:                operation.setElementQName(new QName(defaultNS, name));
1285:                operation.setMethod(method);
1286:
1287:                // If this is a MESSAGE style service, set up the OperationDesc
1288:                // appropriately.
1289:                if (style == Style.MESSAGE) {
1290:                    int messageOperType = checkMessageMethod(method);
1291:                    if (messageOperType == OperationDesc.MSG_METHOD_NONCONFORMING)
1292:                        return;
1293:                    if (messageOperType == -1) {
1294:                        throw new InternalException(
1295:                                "Couldn't match method to any of the allowable message-style patterns!");
1296:                    }
1297:                    operation.setMessageOperationStyle(messageOperType);
1298:                    operation.setReturnClass(Object.class);
1299:                    operation.setReturnType(Constants.XSD_ANYTYPE);
1300:                } else {
1301:                    // For other styles, continue here.
1302:                    Class retClass = method.getReturnType();
1303:                    operation.setReturnClass(retClass);
1304:                    QName typeQName = getTypeQName(retClass);
1305:                    operation.setReturnType(typeQName);
1306:
1307:                    String[] paramNames = getParamNames(method);
1308:
1309:                    for (int k = 0; k < paramTypes.length; k++) {
1310:                        Class type = paramTypes[k];
1311:                        ParameterDesc paramDesc = new ParameterDesc();
1312:                        // param should be unqualified if we're using rpc style,
1313:                        // or should use the operation's namespace if its document style
1314:                        String paramNamespace = (this .style == Style.RPC ? ""
1315:                                : operation.getElementQName().getNamespaceURI());
1316:
1317:                        // If we have a name for this param, use it, otherwise call
1318:                        // it "in*"
1319:                        if (paramNames != null && paramNames[k] != null
1320:                                && paramNames[k].length() > 0) {
1321:                            paramDesc.setQName(new QName(paramNamespace,
1322:                                    paramNames[k]));
1323:                        } else {
1324:                            paramDesc.setQName(new QName(paramNamespace, "in"
1325:                                    + k));
1326:                        }
1327:
1328:                        // If it's a Holder, mark it INOUT, and set the XML type QName
1329:                        // to the held type.  Otherwise it's IN.
1330:
1331:                        Class heldClass = JavaUtils.getHolderValueType(type);
1332:                        if (heldClass != null) {
1333:                            paramDesc.setMode(ParameterDesc.INOUT);
1334:                            paramDesc.setTypeQName(getTypeQName(heldClass));
1335:                        } else {
1336:                            paramDesc.setMode(ParameterDesc.IN);
1337:                            paramDesc.setTypeQName(getTypeQName(type));
1338:                        }
1339:                        paramDesc.setJavaType(type);
1340:                        operation.addParameter(paramDesc);
1341:                    }
1342:                }
1343:
1344:                createFaultMetadata(method, operation);
1345:
1346:                addOperationDesc(operation);
1347:                method2OperationMap.put(method, operation);
1348:            }
1349:
1350:            private QName getTypeQName(Class javaClass) {
1351:                QName typeQName;
1352:                TypeMapping tm = getTypeMapping();
1353:                if (style == Style.RPC) {
1354:                    typeQName = tm.getTypeQName(javaClass);
1355:                } else {
1356:                    typeQName = tm.getTypeQNameExact(javaClass);
1357:                    if (typeQName == null && javaClass.isArray()) {
1358:                        typeQName = tm.getTypeQName(javaClass
1359:                                .getComponentType());
1360:                    } else {
1361:                        typeQName = tm.getTypeQName(javaClass);
1362:                    }
1363:                }
1364:                return typeQName;
1365:            }
1366:
1367:            private void createFaultMetadata(Method method,
1368:                    OperationDesc operation) {
1369:                // Create Exception Types
1370:                Class[] exceptionTypes = method.getExceptionTypes();
1371:
1372:                for (int i = 0; i < exceptionTypes.length; i++) {
1373:                    // Every remote method declares a java.rmi.RemoteException
1374:                    // Only interested in application specific exceptions.
1375:                    // Ignore java and javax package exceptions.
1376:                    Class ex = exceptionTypes[i];
1377:                    if (ex != java.rmi.RemoteException.class
1378:                            && ex != org.apache.axis.AxisFault.class
1379:                            && !ex.getName().startsWith("java.")
1380:                            && !ex.getName().startsWith("javax.")) {
1381:
1382:                        // For JSR 101 v.1.0, there is a simple fault mapping
1383:                        // and a complexType fault mapping...both mappings
1384:                        // generate a class that extends (directly or indirectly)
1385:                        // Exception.
1386:                        // When converting java back to wsdl it is not possible
1387:                        // to determine which way to do the mapping,
1388:                        // so it is always mapped back using the complexType
1389:                        // fault mapping because it is more useful (i.e. it
1390:                        // establishes a hierarchy of exceptions).  Note that this
1391:                        // will not cause any roundtripping problems.
1392:                        // Rich
1393:
1394:                        /* Old Simple Type Mode
1395:                        Field[] f = ex.getDeclaredFields();
1396:                        ArrayList exceptionParams = new ArrayList();
1397:                        for (int j = 0; j < f.length; j++) {
1398:                            int mod = f[j].getModifiers();
1399:                            if (Modifier.isPublic(mod) &&
1400:                                 !Modifier.isStatic(mod)) {
1401:                                QName qname = new QName("", f[j].getName());
1402:                                QName typeQName = tm.getTypeQName(f[j].getType());
1403:                                ParameterDesc param = new ParameterDesc(qname,
1404:                                                                        ParameterDesc.IN,
1405:                                                                        typeQName);
1406:                                param.setJavaType(f[j].getType());
1407:                                exceptionParams.add(param);
1408:                            }
1409:                        }
1410:                        String pkgAndClsName = ex.getName();
1411:                        FaultDesc fault = new FaultDesc();
1412:                        fault.setName(pkgAndClsName);
1413:                        fault.setParameters(exceptionParams);
1414:                        operation.addFault(fault);
1415:                         */
1416:
1417:                        FaultDesc fault = operation.getFaultByClass(ex, false);
1418:                        boolean isNew;
1419:
1420:                        // If we didn't find one, create a new one
1421:                        if (fault == null) {
1422:                            fault = new FaultDesc();
1423:                            isNew = true;
1424:                        } else {
1425:                            isNew = false;
1426:                        }
1427:
1428:                        // Try to fil in any parts of the faultDesc that aren't there
1429:
1430:                        // XMLType
1431:                        QName xmlType = fault.getXmlType();
1432:                        if (xmlType == null) {
1433:                            fault.setXmlType(getTypeMapping().getTypeQName(ex));
1434:                        }
1435:
1436:                        // Name and Class Name
1437:                        String pkgAndClsName = ex.getName();
1438:                        if (fault.getClassName() == null) {
1439:                            fault.setClassName(pkgAndClsName);
1440:                        }
1441:                        if (fault.getName() == null) {
1442:                            String name = pkgAndClsName.substring(pkgAndClsName
1443:                                    .lastIndexOf('.') + 1, pkgAndClsName
1444:                                    .length());
1445:                            fault.setName(name);
1446:                        }
1447:
1448:                        // Parameters
1449:                        // We add a single parameter which points to the type
1450:                        if (fault.getParameters() == null) {
1451:                            if (xmlType == null) {
1452:                                xmlType = getTypeMapping().getTypeQName(ex);
1453:                            }
1454:                            QName qname = fault.getQName();
1455:                            if (qname == null) {
1456:                                qname = new QName("", "fault");
1457:                            }
1458:                            ParameterDesc param = new ParameterDesc(qname,
1459:                                    ParameterDesc.IN, xmlType);
1460:                            param.setJavaType(ex);
1461:                            ArrayList exceptionParams = new ArrayList();
1462:                            exceptionParams.add(param);
1463:                            fault.setParameters(exceptionParams);
1464:                        }
1465:
1466:                        // QName
1467:                        if (fault.getQName() == null) {
1468:                            fault.setQName(new QName(pkgAndClsName));
1469:                        }
1470:
1471:                        if (isNew) {
1472:                            // Add the fault to the operation
1473:                            operation.addFault(fault);
1474:                        }
1475:                    }
1476:                }
1477:            }
1478:
1479:            private String[] getParamNames(Method method) {
1480:                synchronized (method2ParamsMap) {
1481:                    String[] paramNames = (String[]) method2ParamsMap
1482:                            .get(method);
1483:                    if (paramNames != null)
1484:                        return paramNames;
1485:                    paramNames = ParamNameExtractor
1486:                            .getParameterNamesFromDebugInfo(method);
1487:                    method2ParamsMap.put(method, paramNames);
1488:                    return paramNames;
1489:                }
1490:            }
1491:
1492:            public void setNamespaceMappings(List namespaces) {
1493:                namespaceMappings = namespaces;
1494:            }
1495:
1496:            public String getDefaultNamespace() {
1497:                if (namespaceMappings == null || namespaceMappings.isEmpty())
1498:                    return null;
1499:                return (String) namespaceMappings.get(0);
1500:            }
1501:
1502:            public void setDefaultNamespace(String namespace) {
1503:                if (namespaceMappings == null)
1504:                    namespaceMappings = new ArrayList();
1505:                namespaceMappings.add(0, namespace);
1506:            }
1507:
1508:            public void setProperty(String name, Object value) {
1509:                if (properties == null) {
1510:                    properties = new HashMap();
1511:                }
1512:                properties.put(name, value);
1513:            }
1514:
1515:            public Object getProperty(String name) {
1516:                if (properties == null)
1517:                    return null;
1518:
1519:                return properties.get(name);
1520:            }
1521:
1522:            public String getEndpointURL() {
1523:                return endpointURL;
1524:            }
1525:
1526:            public void setEndpointURL(String endpointURL) {
1527:                this .endpointURL = endpointURL;
1528:            }
1529:
1530:            public TypeMappingRegistry getTypeMappingRegistry() {
1531:                if (tmr == null) {
1532:                    tmr = new TypeMappingRegistryImpl(false);
1533:                }
1534:                return tmr;
1535:            }
1536:
1537:            public void setTypeMappingRegistry(TypeMappingRegistry tmr) {
1538:                this .tmr = tmr;
1539:            }
1540:
1541:            public boolean isInitialized() {
1542:                return implClass != null;
1543:            }
1544:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.