001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.websvc.jaxrpc.actions;
043:
044: import com.sun.source.tree.ClassTree;
045: import com.sun.source.tree.MethodTree;
046: import org.netbeans.modules.websvc.api.support.java.SourceUtils;
047: import org.netbeans.modules.websvc.core._RetoucheUtil;
048: import org.netbeans.modules.websvc.core.AddWsOperationHelper;
049: import org.netbeans.modules.websvc.core.AddOperationCookie;
050: import org.openide.filesystems.FileObject;
051: import java.io.IOException;
052: import java.util.ArrayList;
053: import java.util.List;
054: import org.netbeans.api.java.classpath.ClassPath;
055: import org.netbeans.api.java.project.JavaProjectConstants;
056: import org.netbeans.api.java.source.CancellableTask;
057: import org.netbeans.api.java.source.JavaSource;
058: import org.netbeans.api.java.source.TreeMaker;
059: import org.netbeans.api.java.source.WorkingCopy;
060: import org.netbeans.api.project.FileOwnerQuery;
061: import org.netbeans.api.project.Project;
062: import org.netbeans.api.project.ProjectUtils;
063: import org.netbeans.api.project.SourceGroup;
064: import org.netbeans.modules.j2ee.common.method.MethodModel;
065: import org.netbeans.modules.j2ee.common.method.MethodModelSupport;
066: import org.netbeans.modules.j2ee.dd.api.webservices.PortComponent;
067: import org.netbeans.modules.j2ee.dd.api.webservices.DDProvider;
068: import org.netbeans.modules.j2ee.dd.api.webservices.Webservices;
069: import org.netbeans.modules.j2ee.dd.api.webservices.ServiceImplBean;
070: import org.netbeans.modules.j2ee.dd.api.webservices.WebserviceDescription;
071: import org.netbeans.modules.websvc.api.webservices.WebServicesSupport;
072: import static org.netbeans.api.java.source.JavaSource.Phase;
073: import org.openide.ErrorManager;
074: import org.openide.cookies.SaveCookie;
075: import org.openide.filesystems.FileObject;
076: import org.openide.loaders.DataObject;
077: import org.openide.util.NbBundle;
078:
079: /** JaxWsAddOperation.java
080: * Created on December 12, 2006, 4:36 PM
081: *
082: * @author mkuchtiak
083: */
084: public class JaxRpcAddOperation implements AddOperationCookie {
085:
086: private static final String Remote_Exception = "java.rmi.RemoteException"; //NOI18N
087:
088: /** Creates a new instance of JaxWsAddOperation */
089: public JaxRpcAddOperation() {
090: }
091:
092: public void addOperation(FileObject implementationClass) {
093: WebserviceDescription wsDesc = findWSDescriptionFromClass(implementationClass);
094: if (wsDesc == null)
095: return; //this will never happen
096: FileObject implBeanClass;
097: FileObject seiClass;
098: if (!isSEIClass(implementationClass, wsDesc)) {
099: implBeanClass = implementationClass;
100: seiClass = getSEIClass(wsDesc, implementationClass);
101: } else {
102: implBeanClass = getImplementationBean(wsDesc,
103: implementationClass);
104: if (implBeanClass == null)
105: return; // this should never happen
106: seiClass = implementationClass;
107: }
108: AddWsOperationHelper strategy = new AddWsOperationHelper(
109: NbBundle.getMessage(AddWsOperationHelper.class,
110: "LBL_OperationAction"), false);
111: try {
112: String className = _RetoucheUtil
113: .getMainClassName(implBeanClass);
114: if (className != null) {
115: MethodModel methodModel = strategy.getMethodModel(
116: implBeanClass, className);
117: if (methodModel != null && seiClass != null) {
118: addMethodToSEI(methodModel, seiClass);
119: }
120: }
121: } catch (IOException ex) {
122: ErrorManager.getDefault().notify(ex);
123: }
124: }
125:
126: public boolean isEnabledInEditor(FileObject implClass) {
127: return isWsImplBeanOrInterface(implClass);
128: }
129:
130: private boolean hasRemoteException(final List<String> exceptions) {
131: for (String exception : exceptions) {
132: if (exception.equals(Remote_Exception)) {
133: return true;
134: }
135: }
136: return false;
137: }
138:
139: private void addMethodToSEI(final MethodModel methodModel,
140: FileObject seiFo) {
141: final JavaSource targetSource = JavaSource.forFileObject(seiFo);
142: final CancellableTask<WorkingCopy> modificationTask = new CancellableTask<WorkingCopy>() {
143:
144: public void run(WorkingCopy workingCopy) throws IOException {
145: workingCopy.toPhase(Phase.RESOLVED);
146: ClassTree javaClass = SourceUtils
147: .getPublicTopLevelTree(workingCopy);
148: if (javaClass != null) {
149: TreeMaker make = workingCopy.getTreeMaker();
150: List<String> exceptions = new ArrayList<String>();
151: exceptions.addAll(methodModel.getExceptions());
152: if (!hasRemoteException(exceptions)) {
153: exceptions.add(Remote_Exception); //all SEI methods must throw RemoteException
154: }
155: MethodModel seiMethodModel = MethodModel.create(
156: methodModel.getName(), methodModel
157: .getReturnType(), null, methodModel
158: .getParameters(), exceptions,
159: methodModel.getModifiers()); //create an SEI version of MethodModel, no method body
160: MethodTree methodTree = MethodModelSupport
161: .createMethodTree(workingCopy,
162: seiMethodModel);
163: ClassTree modifiedClass = make.addClassMember(
164: javaClass, methodTree);
165: workingCopy.rewrite(javaClass, modifiedClass);
166: }
167: }
168:
169: public void cancel() {
170: }
171: };
172: try {
173: targetSource.runModificationTask(modificationTask).commit();
174: DataObject dataObject = DataObject.find(seiFo);
175: if (dataObject != null) {
176: SaveCookie cookie = dataObject
177: .getCookie(SaveCookie.class);
178: if (cookie != null) {
179: cookie.save();
180: }
181: }
182: } catch (IOException ex) {
183: ErrorManager.getDefault().notify(ex);
184: }
185: }
186:
187: private FileObject getSEIClass(WebserviceDescription wsDesc,
188: FileObject implClass) {
189: PortComponent[] ports = wsDesc.getPortComponent();
190: if (ports.length > 0) {
191: //in the Jaxrpc support, we assume only one port
192: PortComponent portComponent = ports[0];
193: String sei = portComponent.getServiceEndpointInterface();
194: sei = sei.replace(".", "/") + ".java";
195: Project project = FileOwnerQuery.getOwner(implClass);
196: for (SourceGroup srcGroup : ProjectUtils
197: .getSources(project).getSourceGroups(
198: JavaProjectConstants.SOURCES_TYPE_JAVA)) {
199: FileObject seiFO = srcGroup.getRootFolder()
200: .getFileObject(sei);
201: if (seiFO != null) {
202: return seiFO;
203: }
204: }
205: }
206: return null;
207: }
208:
209: private FileObject getImplementationBean(
210: WebserviceDescription wsDesc, FileObject seiClass) {
211: PortComponent[] ports = wsDesc.getPortComponent();
212: if (ports.length > 0) {
213: //in the Jaxrpc support, we assume only one port
214: PortComponent portComponent = ports[0];
215: ServiceImplBean serviceImplBean = portComponent
216: .getServiceImplBean();
217: String link = serviceImplBean.getServletLink();
218: if (link == null) {
219: link = serviceImplBean.getEjbLink();
220: }
221: String implBean = WebServicesSupport.getWebServicesSupport(
222: seiClass).getImplementationBean(link);
223: implBean = implBean.replace(".", "/") + ".java";
224: Project project = FileOwnerQuery.getOwner(seiClass);
225: for (SourceGroup srcGroup : ProjectUtils
226: .getSources(project).getSourceGroups(
227: JavaProjectConstants.SOURCES_TYPE_JAVA)) {
228: FileObject implFO = srcGroup.getRootFolder()
229: .getFileObject(implBean);
230: if (implFO != null) {
231: return implFO;
232: }
233: }
234: }
235: return null;
236: }
237:
238: private boolean isSEIClass(FileObject fileObject,
239: WebserviceDescription wsDesc) {
240: ClassPath classPath = ClassPath.getClassPath(fileObject,
241: ClassPath.SOURCE);
242: String implClassPath = classPath.getResourceName(fileObject,
243: '.', false);
244: PortComponent portComponent = wsDesc.getPortComponent(0);
245: // first check the interface
246: String wsSEI = portComponent.getServiceEndpointInterface();
247: if ((wsSEI != null) && (implClassPath.endsWith(wsSEI))) {
248: return true;
249: }
250: return false;
251: }
252:
253: public static boolean isWsImplBeanOrInterface(FileObject implClassFo) {
254: WebserviceDescription wsDesc = findWSDescriptionFromClass(implClassFo);
255: if (wsDesc != null) {
256: WebServicesSupport wsSupport = WebServicesSupport
257: .getWebServicesSupport(implClassFo);
258: if (wsSupport != null) {
259: return !wsSupport.isFromWSDL(wsDesc
260: .getWebserviceDescriptionName());
261: }
262: }
263: return false;
264: }
265:
266: static WebserviceDescription findWSDescriptionFromClass(
267: FileObject implClassFO) {
268: WebServicesSupport wsSupport = WebServicesSupport
269: .getWebServicesSupport(implClassFO);
270: ClassPath classPath = ClassPath.getClassPath(implClassFO,
271: ClassPath.SOURCE);
272: String implClassPath = classPath.getResourceName(implClassFO,
273: '.', false);
274: if (wsSupport != null) {
275: DDProvider wsDDProvider = DDProvider.getDefault();
276: Webservices webServices = null;
277: try {
278: webServices = wsDDProvider.getDDRoot(wsSupport
279: .getWebservicesDD());
280: } catch (java.io.IOException e) {
281: ErrorManager.getDefault().notify(e);
282: }
283:
284: if (webServices != null) {
285: WebserviceDescription[] wsDescriptions = webServices
286: .getWebserviceDescription();
287: for (int i = 0; i < wsDescriptions.length; i++) {
288: WebserviceDescription wsDescription = wsDescriptions[i];
289: PortComponent portComponent = wsDescription
290: .getPortComponent(0);
291: // first check the interface
292: String wsSEI = portComponent
293: .getServiceEndpointInterface();
294: if ((wsSEI != null)
295: && (implClassPath.endsWith(wsSEI))) {
296: return wsDescription;
297: }
298: // then the implementation bean
299: ServiceImplBean serviceImplBean = portComponent
300: .getServiceImplBean();
301: String link = serviceImplBean.getServletLink();
302: if (link == null) {
303: link = serviceImplBean.getEjbLink();
304: }
305: String implBean = wsSupport
306: .getImplementationBean(link);
307: if (implBean != null
308: && implClassPath.endsWith(implBean)) {
309: return wsDescription;
310: }
311: }
312: }
313: }
314: return null;
315: }
316:
317: }
|