1 /*
2  * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package com.sun.tools.internal.ws.processor.generator;
27 
28 import com.sun.codemodel.internal.ClassType;
29 import com.sun.codemodel.internal.JAnnotationUse;
30 import com.sun.codemodel.internal.JBlock;
31 import com.sun.codemodel.internal.JClass;
32 import com.sun.codemodel.internal.JClassAlreadyExistsException;
33 import com.sun.codemodel.internal.JDefinedClass;
34 import com.sun.codemodel.internal.JDocComment;
35 import com.sun.codemodel.internal.JExpr;
36 import com.sun.codemodel.internal.JFieldRef;
37 import com.sun.codemodel.internal.JFieldVar;
38 import com.sun.codemodel.internal.JMethod;
39 import com.sun.codemodel.internal.JMod;
40 import com.sun.codemodel.internal.JType;
41 import com.sun.codemodel.internal.JVar;
42 import com.sun.tools.internal.ws.processor.model.Fault;
43 import com.sun.tools.internal.ws.processor.model.Model;
44 import com.sun.tools.internal.ws.wscompile.ErrorReceiver;
45 import com.sun.tools.internal.ws.wscompile.WsimportOptions;
46 
47 import javax.xml.ws.WebFault;
48 import java.util.HashMap;
49 import java.util.Map;
50 
51 /**
52  *
53  * @author WS Development Team
54  */
55 public class CustomExceptionGenerator extends GeneratorBase {
56     private Map<String, JClass> faults = new HashMap<String, JClass>();
57 
generate(Model model, WsimportOptions options, ErrorReceiver receiver)58     public static void generate(Model model,
59         WsimportOptions options,
60         ErrorReceiver receiver){
61         CustomExceptionGenerator exceptionGen = new CustomExceptionGenerator();
62         exceptionGen.init(model, options, receiver);
63         exceptionGen.doGeneration();
64     }
65 
getGenerator(Model model, WsimportOptions options, ErrorReceiver receiver)66     public GeneratorBase getGenerator(Model model, WsimportOptions options, ErrorReceiver receiver) {
67         GeneratorBase g = new CustomExceptionGenerator();
68         g.init(model, options, receiver);
69         return g;
70     }
71 
72     @Override
visit(Fault fault)73     public void visit(Fault fault) throws Exception {
74         if (isRegistered(fault))
75             return;
76         registerFault(fault);
77     }
78 
isRegistered(Fault fault)79     private boolean isRegistered(Fault fault) {
80         if(faults.keySet().contains(fault.getJavaException().getName())){
81             fault.setExceptionClass(faults.get(fault.getJavaException().getName()));
82             return true;
83         }
84         return false;
85     }
86 
registerFault(Fault fault)87     private void registerFault(Fault fault) {
88          try {
89             write(fault);
90             faults.put(fault.getJavaException().getName(), fault.getExceptionClass());
91         } catch (JClassAlreadyExistsException e) {
92             throw new GeneratorException("generator.nestedGeneratorError",e);
93         }
94     }
95 
write(Fault fault)96     private void write(Fault fault) throws JClassAlreadyExistsException {
97         String className = Names.customExceptionClassName(fault);
98 
99         JDefinedClass cls = cm._class(className, ClassType.CLASS);
100         JDocComment comment = cls.javadoc();
101         if(fault.getJavaDoc() != null){
102             comment.add(fault.getJavaDoc());
103             comment.add("\n\n");
104         }
105 
106         for (String doc : getJAXWSClassComment()) {
107             comment.add(doc);
108         }
109 
110         cls._extends(java.lang.Exception.class);
111 
112         //@WebFault
113         JAnnotationUse faultAnn = cls.annotate(WebFault.class);
114         faultAnn.param("name", fault.getBlock().getName().getLocalPart());
115         faultAnn.param("targetNamespace", fault.getBlock().getName().getNamespaceURI());
116 
117         JType faultBean = fault.getBlock().getType().getJavaType().getType().getType();
118 
119         //faultInfo filed
120         JFieldVar fi = cls.field(JMod.PRIVATE, faultBean, "faultInfo");
121 
122         //add jaxb annotations
123         fault.getBlock().getType().getJavaType().getType().annotate(fi);
124 
125         fi.javadoc().add("Java type that goes as soapenv:Fault detail element.");
126         JFieldRef fr = JExpr.ref(JExpr._this(), fi);
127 
128         //Constructor
129         JMethod constrc1 = cls.constructor(JMod.PUBLIC);
130         JVar var1 = constrc1.param(String.class, "message");
131         JVar var2 = constrc1.param(faultBean, "faultInfo");
132         constrc1.javadoc().addParam(var1);
133         constrc1.javadoc().addParam(var2);
134         JBlock cb1 = constrc1.body();
135         cb1.invoke("super").arg(var1);
136 
137         cb1.assign(fr, var2);
138 
139         //constructor with Throwable
140         JMethod constrc2 = cls.constructor(JMod.PUBLIC);
141         var1 = constrc2.param(String.class, "message");
142         var2 = constrc2.param(faultBean, "faultInfo");
143         JVar var3 = constrc2.param(Throwable.class, "cause");
144         constrc2.javadoc().addParam(var1);
145         constrc2.javadoc().addParam(var2);
146         constrc2.javadoc().addParam(var3);
147         JBlock cb2 = constrc2.body();
148         cb2.invoke("super").arg(var1).arg(var3);
149         cb2.assign(fr, var2);
150 
151 
152         //getFaultInfo() method
153         JMethod fim = cls.method(JMod.PUBLIC, faultBean, "getFaultInfo");
154         fim.javadoc().addReturn().add("returns fault bean: "+faultBean.fullName());
155         JBlock fib = fim.body();
156         fib._return(fi);
157         fault.setExceptionClass(cls);
158 
159     }
160 }
161