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 
  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 
  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
  73     public void visit(Fault fault) throws Exception {
  74         if (isRegistered(fault))
  75             return;
  76         registerFault(fault);
  77     }
  78 
  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 
  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 
  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 }