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.dev.wizard;
043:
044: import com.sun.source.tree.ClassTree;
045: import java.io.File;
046: import java.io.IOException;
047: import java.net.URI;
048: import java.text.DateFormat;
049: import java.util.ArrayList;
050: import java.util.Date;
051: import java.util.List;
052: import javax.xml.transform.stream.StreamSource;
053: import org.apache.tools.ant.module.api.support.ActionUtils;
054: import org.netbeans.api.java.source.CancellableTask;
055: import org.netbeans.api.java.source.Comment;
056: import org.netbeans.api.java.source.Comment.Style;
057: import org.netbeans.api.java.source.JavaSource;
058: import org.netbeans.api.java.source.JavaSource.Phase;
059: import org.netbeans.api.java.source.TreeMaker;
060: import org.netbeans.api.java.source.WorkingCopy;
061: import org.netbeans.api.progress.ProgressHandle;
062: import org.netbeans.api.progress.ProgressHandleFactory;
063: import org.netbeans.api.project.Project;
064: import org.netbeans.modules.websvc.api.support.java.SourceUtils;
065: import org.netbeans.modules.websvc.api.webservices.WebServicesSupport;
066: import org.netbeans.modules.websvc.api.webservices.WsCompileEditorSupport;
067: import org.netbeans.modules.websvc.core.ServiceCreator;
068: import org.netbeans.modules.websvc.core.ProjectInfo;
069: import org.netbeans.spi.project.support.ant.GeneratedFilesHelper;
070: import org.netbeans.spi.project.ui.templates.support.Templates;
071: import org.openide.DialogDisplayer;
072: import org.openide.ErrorManager;
073: import org.openide.NotifyDescriptor;
074: import org.openide.WizardDescriptor;
075: import org.openide.cookies.EditorCookie;
076: import org.openide.cookies.SaveCookie;
077: import org.openide.execution.ExecutorTask;
078: import org.openide.filesystems.FileLock;
079: import org.openide.filesystems.FileObject;
080: import org.openide.filesystems.FileUtil;
081: import org.openide.loaders.DataObject;
082: import org.openide.loaders.DataObjectNotFoundException;
083: import org.openide.util.NbBundle;
084: import org.openide.util.RequestProcessor;
085:
086: /**
087: *
088: * @author Ajit Bhate
089: */
090: public class JaxRpcServiceCreator implements ServiceCreator {
091: private static final String WSDL_FILE_PATH = "wsdlFilePath"; //NOI18N
092:
093: private Project project;
094: private ProjectInfo projectInfo;
095: private WizardDescriptor wiz;
096: private String wsName;
097:
098: /** Creates a new instance of JaxRpcServiceCreator */
099: public JaxRpcServiceCreator(Project project,
100: ProjectInfo projectInfo, WizardDescriptor wiz) {
101: this .project = project;
102: this .projectInfo = projectInfo;
103: this .wiz = wiz;
104: }
105:
106: public void createService() throws IOException {
107: // Use Progress API to display generator messages.
108: final ProgressHandle handle = ProgressHandleFactory
109: .createHandle(NbBundle.getMessage(
110: JaxRpcServiceCreator.class,
111: "TXT_WebServiceGeneration")); //NOI18N
112: handle.start(100);
113:
114: Runnable r = new Runnable() {
115: public void run() {
116: try {
117: generateWebService(handle);
118: } catch (Exception e) {
119: //finish progress bar
120: handle.finish();
121: String message = e.getLocalizedMessage();
122: if (message != null) {
123: ErrorManager.getDefault().notify(
124: ErrorManager.INFORMATIONAL, e);
125: NotifyDescriptor nd = new NotifyDescriptor.Message(
126: message, NotifyDescriptor.ERROR_MESSAGE);
127: DialogDisplayer.getDefault().notify(nd);
128: } else {
129: ErrorManager.getDefault().notify(
130: ErrorManager.EXCEPTION, e);
131: }
132: }
133: }
134: };
135: RequestProcessor.getDefault().post(r);
136:
137: }
138:
139: public void createServiceFromWsdl() throws IOException {
140: final ProgressHandle handle = ProgressHandleFactory
141: .createHandle(NbBundle.getMessage(
142: JaxRpcServiceCreator.class,
143: "TXT_WebServiceGeneration")); //NOI18N
144:
145: Runnable r = new Runnable() {
146: public void run() {
147: try {
148: handle.start(100);
149: generateWsFromWsdl(handle);
150: } catch (Exception e) {
151: //finish progress bar
152: handle.finish();
153: String message = e.getLocalizedMessage();
154: if (message != null) {
155: ErrorManager.getDefault().notify(
156: ErrorManager.INFORMATIONAL, e);
157: NotifyDescriptor nd = new NotifyDescriptor.Message(
158: message, NotifyDescriptor.ERROR_MESSAGE);
159: DialogDisplayer.getDefault().notify(nd);
160: } else {
161: ErrorManager.getDefault().notify(
162: ErrorManager.EXCEPTION, e);
163: }
164: }
165: }
166: };
167: RequestProcessor.getDefault().post(r);
168:
169: }
170:
171: private void generateWebService(ProgressHandle handle)
172: throws Exception {
173: FileObject pkg = Templates.getTargetFolder(wiz);
174: WebServicesSupport wsSupport = WebServicesSupport
175: .getWebServicesSupport(pkg);
176: assert wsSupport != null;
177:
178: wsName = getUniqueJaxrpcName(wsSupport, Templates
179: .getTargetName(wiz));
180:
181: WebServiceGenerator generator = new WebServiceGenerator(
182: wsSupport, wsName, pkg, project);
183: handle.progress(NbBundle.getMessage(JaxRpcServiceCreator.class,
184: "MSG_GEN_SEI_AND_IMPL"), 50); //NOI18N
185: generator.generateWebService();
186:
187: URI targetNS = null;
188: URI typeNS = null;
189: try {
190: targetNS = generator.getTargetNS();
191: typeNS = generator.getDefaultTypeNS(wsName); //Need to get from user
192: } catch (java.net.URISyntaxException e) {
193: String mes = NbBundle.getMessage(
194: JaxRpcServiceCreator.class,
195: "MSG_INVALID_URL_SYNTAX"); //NOI18N
196: throw new Exception(mes);
197: }
198: //Create config file
199: handle.progress(NbBundle.getMessage(JaxRpcServiceCreator.class,
200: "MSG_CREATING_WSCOMPILE_ARTIFACTS")); //NOI18N
201: String servantClassName = generator.getServantClassName();
202: String seiClassName = generator.getSEIClassName();
203: FileObject configFile = null;
204: configFile = generator.generateConfigFile(seiClassName,
205: servantClassName, targetNS, typeNS);
206: handle.progress(70);
207:
208: //Add web service entries to the project's property file, project file
209: wsSupport.addServiceImpl(wsName, configFile, false);
210: handle.progress(90);
211:
212: //Add web service entries to the module's DD
213: wsSupport.addServiceEntriesToDD(wsName, seiClassName,
214: servantClassName);
215:
216: //Add webservice entry in webservices.xml
217: handle.progress(NbBundle.getMessage(JaxRpcServiceCreator.class,
218: "MSG_ADDING_DD_ENTRIES")); //NOI18N
219: String portTypeName = null;
220: generator.addWebServiceEntry(seiClassName, portTypeName,
221: targetNS);
222:
223: //open the class in the editor
224: FileObject servantFO = pkg.getFileObject(wsName + "Impl",
225: "java");
226: if (servantFO != null) {
227: try {
228: DataObject dobj = DataObject.find(servantFO);
229: EditorCookie ec = dobj.getCookie(EditorCookie.class);
230: ec.open();
231: } catch (DataObjectNotFoundException donfe) {
232: }
233: }
234:
235: handle.finish();
236: }
237:
238: private void generateWsFromWsdl(ProgressHandle handle)
239: throws Exception {
240: FileObject pkg = Templates.getTargetFolder(wiz);
241: wsName = Templates.getTargetName(wiz);
242: WebServicesSupport wsSupport = WebServicesSupport
243: .getWebServicesSupport(pkg);
244: assert wsSupport != null;
245: WebServiceGenerator generator = new WebServiceGenerator(
246: wsSupport, wsName, pkg, project);
247:
248: //coming from wsdl
249: FileObject wsDDFolder = wsSupport.getWsDDFolder();
250: //get wsdl folder, if none, create it
251: FileObject wsdlFolder = wsDDFolder.getFileObject("wsdl"); //NOI18N
252: if (wsdlFolder == null) {
253: wsdlFolder = wsDDFolder.createFolder("wsdl"); //NOI18N
254: }
255:
256: handle.progress(NbBundle.getMessage(JaxRpcServiceCreator.class,
257: "MSG_PARSING_WSDL"), 30); //NOI18N
258: String wsdlFilePath = (String) wiz.getProperty(WSDL_FILE_PATH);
259: File normalizedWsdlFilePath = FileUtil.normalizeFile(new File(
260: wsdlFilePath));
261: final FileObject sourceWsdlFile = FileUtil
262: .toFileObject(normalizedWsdlFilePath);
263: if (sourceWsdlFile == null) {
264: String mes = NbBundle.getMessage(
265: JaxRpcServiceCreator.class,
266: "MSG_CANNOT_GET_FILE_OBJECT",
267: normalizedWsdlFilePath.getAbsolutePath()); //NOI18N
268: throw new IOException(mes);
269: }
270: String changedWsName = null;
271: try {
272: changedWsName = generator.parseWSDL(sourceWsdlFile
273: .getInputStream());
274: } catch (NoWSPortDefinedException exc) {
275: ErrorManager.getDefault().log(ErrorManager.INFORMATIONAL,
276: "WSDL does not contain any defined ports"); //NOI18N
277: String mes = NbBundle
278: .getMessage(JaxRpcServiceCreator.class,
279: "ERR_WsdlNoPortDefined"); // NOI18N
280: NotifyDescriptor desc = new NotifyDescriptor.Message(mes,
281: NotifyDescriptor.Message.ERROR_MESSAGE);
282: DialogDisplayer.getDefault().notify(desc);
283: handle.finish();
284: return;
285: }
286: if (changedWsName == null)
287: changedWsName = wsName;
288: handle.progress(NbBundle.getMessage(JaxRpcServiceCreator.class,
289: "MSG_CREATING_NEW_WSDL"), 50); //NOI18N
290: FileObject wsdlFO = generator.generateWSDL(
291: WebServiceGenerator.WSDL_TEMPLATE, changedWsName,
292: generator.getSoapBinding(),
293: generator.getPortTypeName(), wsdlFolder, sourceWsdlFile
294: .getParent(), wsName, new StreamSource(
295: sourceWsdlFile.getInputStream()));
296:
297: URI targetNS = null;
298: URI typeNS = null;
299: try {
300: targetNS = generator.getTargetNS();
301: typeNS = generator.getDefaultTypeNS(wsName); //Need to get from user
302: } catch (java.net.URISyntaxException e) {
303: String mes = NbBundle.getMessage(
304: JaxRpcServiceCreator.class,
305: "MSG_INVALID_URL_SYNTAX"); //NOI18N
306: throw new Exception(mes);
307: }
308:
309: //Create config file
310: handle.progress(NbBundle.getMessage(JaxRpcServiceCreator.class,
311: "MSG_CREATING_WSCOMPILE_ARTIFACTS"), 60); //NOI18N
312: String servantClassName = generator.getServantClassName();
313: String seiClassName = generator.getSEIClassName();
314: FileObject configFile = null;
315:
316: File wsdlFile = FileUtil.toFile(wsdlFO);
317: URI wsdlURI = wsdlFile.toURI();
318: configFile = generator.generateConfigFile(wsdlURI);
319: //Add web service entries to the project's property file, project file
320: wsSupport.addServiceImpl(wsName, configFile, true, generator
321: .getWscompileFeatures());
322:
323: //run the wscompile ant target
324: handle.progress(NbBundle.getMessage(JaxRpcServiceCreator.class,
325: "MSG_RUNNING_WSCOMPILE_TARGET"), 70); //NOI18N
326: String targetName = wsName + "_wscompile"; //NOI18N
327: ExecutorTask task = ActionUtils.runTarget(findBuildXml(),
328: new String[] { targetName }, null);
329: task.waitFinished();
330: if (task.result() != 0) {
331: String mes = NbBundle.getMessage(
332: JaxRpcServiceCreator.class,
333: "MSG_WSCOMPILE_UNSUCCESSFUL"); //NOI18N
334: wsSupport.removeProjectEntries(wsName);
335: try {
336: deleteFile(configFile);
337: deleteFile(wsdlFO);
338: } catch (IOException e) {
339: String message = NbBundle.getMessage(
340: JaxRpcServiceCreator.class,
341: "MSG_UNABLE_DELETE_FILES"); //NOI18N
342: NotifyDescriptor nd = new NotifyDescriptor.Message(
343: message, NotifyDescriptor.ERROR_MESSAGE);
344: DialogDisplayer.getDefault().notify(nd);
345: //let this through
346: }
347: throw new Exception(mes);
348: }
349: handle.progress(80);
350: String implClassName = servantClassName
351: .substring(servantClassName.lastIndexOf(".") + 1); //NOI18N
352: FileObject clz = pkg.getFileObject(implClassName, "java"); //NOI18N
353: DataObject dobj = DataObject.find(clz);
354: //commented due to Retouche Bug
355: //addHeaderComments(wsName, dobj);
356: wsSupport.addInfrastructure(implClassName, pkg);
357:
358: //Add web service entries to the module's DD
359: wsSupport.addServiceEntriesToDD(wsName, seiClassName,
360: servantClassName);
361:
362: //Add webservice entry in webservices.xml
363: handle.progress(NbBundle.getMessage(JaxRpcServiceCreator.class,
364: "MSG_ADDING_DD_ENTRIES"), 90); //NOI18N
365: String portTypeName = null;
366:
367: portTypeName = generator.getPortTypeName();
368:
369: generator.addWebServiceEntry(seiClassName, portTypeName,
370: targetNS);
371:
372: //open the class in the editor
373: EditorCookie ec = dobj.getCookie(EditorCookie.class);
374: ec.open();
375:
376: handle.finish();
377: }
378:
379: private FileObject findBuildXml() {
380: return project.getProjectDirectory().getFileObject(
381: GeneratedFilesHelper.BUILD_XML_PATH);
382: }
383:
384: private void deleteFile(FileObject file) throws IOException {
385: FileLock lock = null;
386: try {
387: lock = file.lock();
388: file.delete(lock);
389: } finally {
390: if (lock != null) {
391: lock.releaseLock();
392: }
393: }
394: }
395:
396: private void addHeaderComments(final String wsName,
397: final DataObject dataObject) {
398: final JavaSource targetSource = JavaSource
399: .forFileObject(dataObject.getPrimaryFile());
400: final ProgressHandle handle = ProgressHandleFactory
401: .createHandle("Adding operation");
402: handle.start(100);
403: final CancellableTask<WorkingCopy> modificationTask = new CancellableTask<WorkingCopy>() {
404: public void run(WorkingCopy workingCopy) throws IOException {
405: workingCopy.toPhase(Phase.RESOLVED);
406: TreeMaker make = workingCopy.getTreeMaker();
407: ClassTree javaClass = SourceUtils
408: .getPublicTopLevelTree(workingCopy);
409: handle.progress(70);
410: // create new (annotated) method
411: StringBuffer buffer = new StringBuffer(NbBundle
412: .getMessage(JaxRpcServiceCreator.class,
413: "MSG_WS_CLASS_COMMENT", wsName)
414: + "\n"); //NOI18N
415: buffer.append(NbBundle.getMessage(
416: JaxRpcServiceCreator.class,
417: "MSG_CREATED_COMMENT")
418: + " "
419: + DateFormat.getDateTimeInstance().format(
420: new Date()) + "\n"); //NOI18N
421: buffer.append("@author "
422: + System.getProperty("user.name")); //NOI18N
423: Comment comment = Comment.create(Style.JAVADOC, 0, 0,
424: 0, buffer.toString());
425: make.addComment(javaClass, comment, true);
426: handle.progress(90);
427: }
428:
429: public void cancel() {
430: }
431: };
432: RequestProcessor.getDefault().post(new Runnable() {
433: public void run() {
434: try {
435: targetSource.runModificationTask(modificationTask)
436: .commit();
437: SaveCookie cookie = dataObject
438: .getCookie(SaveCookie.class);
439: if (cookie != null)
440: cookie.save();
441: } catch (IOException ex) {
442: ErrorManager.getDefault().notify(ex);
443: } finally {
444: handle.finish();
445: }
446: }
447: });
448:
449: }
450:
451: private String getUniqueJaxrpcName(WebServicesSupport wsSupport,
452: String origName) {
453: List<WsCompileEditorSupport.ServiceSettings> webServices = wsSupport
454: .getServices();
455: List<String> serviceNames = new ArrayList<String>(webServices
456: .size());
457: for (WsCompileEditorSupport.ServiceSettings service : webServices) {
458: serviceNames.add(service.getServiceName());
459: }
460: return uniqueWSName(origName, serviceNames);
461: }
462:
463: private String uniqueWSName(final String origName,
464: List<String> names) {
465: int uniquifier = 0;
466: String truename = origName;
467: while (names.contains(truename)) {
468: truename = origName + String.valueOf(++uniquifier);
469: }
470: return truename;
471: }
472: }
|