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.client.wizard;
043:
044: import java.io.File;
045: import java.io.IOException;
046: import java.io.OutputStream;
047: import java.net.URL;
048: import java.util.ArrayList;
049: import java.util.Collections;
050: import java.util.HashMap;
051: import java.util.HashSet;
052: import java.util.Iterator;
053: import java.util.List;
054: import java.util.Map;
055: import java.util.Set;
056: import org.netbeans.api.java.classpath.ClassPath;
057: import org.netbeans.api.java.project.JavaProjectConstants;
058: import org.netbeans.api.java.queries.UnitTestForSourceQuery;
059: import org.netbeans.api.progress.ProgressHandle;
060: import org.netbeans.api.progress.ProgressHandleFactory;
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.api.project.libraries.Library;
065: import org.netbeans.api.project.libraries.LibraryManager;
066: import org.netbeans.modules.j2ee.deployment.devmodules.api.Deployment;
067: import org.netbeans.modules.j2ee.deployment.devmodules.api.J2eePlatform;
068: import org.netbeans.modules.j2ee.deployment.devmodules.spi.J2eeModuleProvider;
069: import org.netbeans.modules.websvc.api.client.ClientStubDescriptor;
070: import org.netbeans.modules.websvc.api.client.WebServicesClientSupport;
071: import org.netbeans.modules.websvc.core.ClientCreator;
072: import org.netbeans.modules.websvc.core.ClientWizardProperties;
073: import org.netbeans.modules.websvc.core.WsdlRetriever;
074: import org.netbeans.modules.websvc.core.WsdlRetriever;
075: import org.netbeans.spi.java.project.classpath.ProjectClassPathExtender;
076: import org.openide.DialogDisplayer;
077: import org.openide.ErrorManager;
078: import org.openide.NotifyDescriptor;
079: import org.openide.WizardDescriptor;
080: import org.openide.filesystems.FileAlreadyLockedException;
081: import org.openide.filesystems.FileLock;
082: import org.openide.filesystems.FileObject;
083: import org.openide.filesystems.FileUtil;
084: import org.openide.filesystems.URLMapper;
085: import org.openide.util.NbBundle;
086: import org.openide.util.RequestProcessor;
087: import org.openide.util.Task;
088:
089: /**
090: *
091: * @author radko
092: */
093: public class JaxRpcClientCreator implements ClientCreator {
094:
095: private static JaxRpcClientCreator instance;
096: private Project project;
097: private WizardDescriptor wiz;
098:
099: private static final boolean DEBUG = false;
100: private static final int JSE_PROJECT_TYPE = 0;
101: private static final int WEB_PROJECT_TYPE = 1;
102: private static final int EJB_PROJECT_TYPE = 2;
103: private static final int CAR_PROJECT_TYPE = 3;
104:
105: /**
106: * Creates a new instance of WebServiceClientCreator
107: */
108: public JaxRpcClientCreator(Project project, WizardDescriptor wiz) {
109: this .project = project;
110: this .wiz = wiz;
111: }
112:
113: public void createClient() throws IOException {
114:
115: final boolean isJsr109Supported = isJsr109Supported();
116: final boolean isJsr109OldSupported = isJsr109OldSupported();
117: final boolean isJWSDPSupported = isJWSDPSupported();
118:
119: // Use Progress API to display generator messages.
120: final ProgressHandle handle = ProgressHandleFactory
121: .createHandle(NbBundle.getMessage(
122: JaxRpcClientCreator.class,
123: "MSG_WizCreateClient")); //NOI18N
124:
125: task = new Task(new Runnable() {
126: public void run() {
127: try {
128: handle.start(100);
129: generate14Client(handle);
130: } catch (IOException exc) {
131: //finish progress bar
132: handle.finish();
133:
134: ErrorManager.getDefault().notify(
135: ErrorManager.EXCEPTION, exc);
136: }
137: }
138: });
139: RequestProcessor.getDefault().post(task);
140: }
141:
142: private String getWsdlName(String wsdlUrl) {
143: int ind = wsdlUrl.lastIndexOf("/"); //NOI18N
144: String wsdlName = ind >= 0 ? wsdlUrl.substring(ind + 1)
145: : wsdlUrl;
146: if (wsdlName.toUpperCase().endsWith("?WSDL"))
147: wsdlName = wsdlName.substring(0, wsdlName.length() - 5); //NOI18N
148: ind = wsdlName.lastIndexOf(".wsdl"); //NOI18N
149: if (ind > 0)
150: wsdlName = wsdlName.substring(0, ind);
151: // replace special characters with '_'
152: return convertAllSpecialChars(wsdlName);
153: }
154:
155: private String convertAllSpecialChars(String resultStr) {
156: StringBuffer sb = new StringBuffer(resultStr);
157: for (int i = 0; i < sb.length(); i++) {
158: char c = sb.charAt(i);
159: if (Character.isLetterOrDigit(c) || (c == '/')
160: || (c == '.') || (c == '_') || (c == ' ')
161: || (c == '-')) {
162: continue;
163: } else {
164: sb.setCharAt(i, '_');
165: }
166: }
167: return sb.toString();
168: }
169:
170: private void generate14Client(final ProgressHandle handle)
171: throws IOException {
172: // Steps:
173: // 1. invoke wizard to select which service to add a reference to.
174: // How to interpret node input set --
175: // + empty: wizard forces project selection, then service selection
176: // + client node: determine project and start on service page
177: // + wsdl node: would select project, but not service. would also
178: // have to verify that WSDL is fully formed.
179:
180: WebServicesClientSupport clientSupport = null;
181:
182: // !PW Get client support from project (from first page of wizard)
183: if (project != null) {
184: clientSupport = WebServicesClientSupport
185: .getWebServicesClientSupport(project
186: .getProjectDirectory());
187: }
188:
189: if (clientSupport == null) {
190: // notify no client support
191: // String mes = MessageFormat.format (
192: // NbBundle.getMessage (WebServiceClientWizardIterator.class, "ERR_WebServiceClientSupportNotFound"),
193: // new Object [] {"Servlet Listener"}); //NOI18N
194: String mes = NbBundle.getMessage(JaxRpcClientCreator.class,
195: "ERR_NoWebServiceClientSupport"); // NOI18N
196: NotifyDescriptor desc = new NotifyDescriptor.Message(mes,
197: NotifyDescriptor.Message.ERROR_MESSAGE);
198: DialogDisplayer.getDefault().notify(desc);
199: return;
200: }
201:
202: final byte[] sourceWsdlDownload = (byte[]) wiz
203: .getProperty(ClientWizardProperties.WSDL_DOWNLOAD_FILE);
204: final List /*WsdlRetriever.SchemaInfo */downloadedSchemas = (List) wiz
205: .getProperty(ClientWizardProperties.WSDL_DOWNLOAD_SCHEMAS);
206: String wsdlFilePath = (String) wiz
207: .getProperty(ClientWizardProperties.WSDL_FILE_PATH);
208: String packageName = (String) wiz
209: .getProperty(ClientWizardProperties.WSDL_PACKAGE_NAME);
210: ClientStubDescriptor stubDescriptor = (ClientStubDescriptor) wiz
211: .getProperty(ClientWizardProperties.CLIENT_STUB_TYPE);
212:
213: String sourceUrl;
214: FileObject sourceWsdlFile = null;
215:
216: if (sourceWsdlDownload == null) {
217: // Verify the existence of the source WSDL file and that we can get a file object for it.
218: File normalizedWsdlFilePath = FileUtil
219: .normalizeFile(new File(wsdlFilePath));
220: sourceUrl = normalizedWsdlFilePath.toString();
221: sourceWsdlFile = FileUtil
222: .toFileObject(normalizedWsdlFilePath);
223:
224: if (sourceWsdlFile == null) {
225: String mes = NbBundle.getMessage(
226: JaxRpcClientCreator.class,
227: "ERR_WsdlFileNotFound", normalizedWsdlFilePath); // NOI18N
228: NotifyDescriptor desc = new NotifyDescriptor.Message(
229: mes, NotifyDescriptor.Message.ERROR_MESSAGE);
230: DialogDisplayer.getDefault().notify(desc);
231: return;
232: }
233: } else {
234: // create a temporary WSDL file
235: File wsdlFile = new File(System
236: .getProperty("java.io.tmpdir"), wsdlFilePath);
237: if (!wsdlFile.exists()) {
238: try {
239: wsdlFile.createNewFile();
240: } catch (IOException ex) {
241: String mes = NbBundle.getMessage(
242: JaxRpcClientCreator.class,
243: "ERR_UnableToCreateTempFile", wsdlFile
244: .getPath()); // NOI18N
245: NotifyDescriptor desc = new NotifyDescriptor.Message(
246: mes, NotifyDescriptor.Message.ERROR_MESSAGE);
247: DialogDisplayer.getDefault().notify(desc);
248: return;
249: }
250: }
251:
252: sourceUrl = (String) wiz
253: .getProperty(ClientWizardProperties.WSDL_DOWNLOAD_URL);
254: sourceWsdlFile = FileUtil.toFileObject(FileUtil
255: .normalizeFile(wsdlFile));
256:
257: if (sourceWsdlFile != null) {
258: FileLock wsdlLock = sourceWsdlFile.lock();
259:
260: try {
261: OutputStream out = sourceWsdlFile
262: .getOutputStream(wsdlLock);
263: try {
264: out.write(sourceWsdlDownload);
265: out.flush();
266: } finally {
267: if (out != null) {
268: out.close();
269: }
270: }
271: } finally {
272: wsdlLock.releaseLock();
273: }
274: } else {
275: String mes = NbBundle.getMessage(
276: JaxRpcClientCreator.class,
277: "ERR_UnableToCreateTempFile", wsdlFile
278: .getPath()); // NOI18N
279: NotifyDescriptor desc = new NotifyDescriptor.Message(
280: mes, NotifyDescriptor.Message.ERROR_MESSAGE);
281: DialogDisplayer.getDefault().notify(desc);
282: return;
283: }
284:
285: // create temporary Schema Files
286: if (downloadedSchemas != null) {
287: Iterator it = downloadedSchemas.iterator();
288: while (it.hasNext()) {
289: WsdlRetriever.SchemaInfo schemaInfo = (WsdlRetriever.SchemaInfo) it
290: .next();
291: File schemalFile = new File(System
292: .getProperty("java.io.tmpdir"), schemaInfo
293: .getSchemaName());
294: try {
295: schemalFile.createNewFile();
296: } catch (IOException ex) {
297: String mes = NbBundle.getMessage(
298: JaxRpcClientCreator.class,
299: "ERR_UnableToCreateTempFile",
300: schemalFile.getPath()); // NOI18N
301: NotifyDescriptor desc = new NotifyDescriptor.Message(
302: mes,
303: NotifyDescriptor.Message.ERROR_MESSAGE);
304: DialogDisplayer.getDefault().notify(desc);
305: return;
306: }
307: FileObject schemaFo = FileUtil
308: .toFileObject(FileUtil
309: .normalizeFile(schemalFile));
310: if (schemaFo != null) {
311: FileLock lock = schemaFo.lock();
312:
313: try {
314: OutputStream out = schemaFo
315: .getOutputStream(lock);
316: try {
317: out
318: .write(schemaInfo
319: .getSchemaContent());
320: out.flush();
321: } finally {
322: if (out != null) {
323: out.close();
324: }
325: }
326: } finally {
327: lock.releaseLock();
328: }
329: } else {
330: String mes = NbBundle.getMessage(
331: JaxRpcClientCreator.class,
332: "ERR_UnableToCreateTempFile",
333: schemalFile.getPath()); // NOI18N
334: NotifyDescriptor desc = new NotifyDescriptor.Message(
335: mes,
336: NotifyDescriptor.Message.ERROR_MESSAGE);
337: DialogDisplayer.getDefault().notify(desc);
338: return;
339: }
340: } //end while
341: } // end if
342: } //end else
343:
344: // 2. add jax-rpc library if wscompile isnt present
345: SourceGroup[] sgs = getJavaSourceGroups(project);
346: ClassPath classPath = ClassPath.getClassPath(sgs[0]
347: .getRootFolder(), ClassPath.COMPILE);
348:
349: FileObject wscompileFO = classPath
350: .findResource("com/sun/xml/rpc/tools/ant/Wscompile.class");
351: if (wscompileFO == null) {
352: // add jax-rpc16 if webservice is not on classpath
353: ProjectClassPathExtender pce = (ProjectClassPathExtender) project
354: .getLookup().lookup(ProjectClassPathExtender.class);
355: Library jaxrpclib = LibraryManager.getDefault().getLibrary(
356: "jaxrpc16"); //NOI18N
357: if ((pce != null) && (jaxrpclib != null)) {
358: pce.addLibrary(jaxrpclib);
359: }
360: }
361:
362: // sets JVM Proxy Options
363: clientSupport.setProxyJVMOptions(System
364: .getProperty("http.proxyHost"), System
365: .getProperty("http.proxyPort"));
366:
367: // 3. add the service client to the project.
368: // Use Progress API to display generator messages.
369: final ClientBuilder builder = new ClientBuilder(project,
370: clientSupport, sourceWsdlFile, packageName, sourceUrl,
371: stubDescriptor);
372: final FileObject sourceWsdlFileTmp = sourceWsdlFile;
373:
374: org.openide.util.RequestProcessor.getDefault().post(
375: new Runnable() {
376: public void run() {
377: try {
378: builder.generate(handle);
379:
380: if (sourceWsdlDownload != null) {
381: // we used a temp file, delete it now.
382: try {
383: sourceWsdlFileTmp.delete();
384: } catch (FileAlreadyLockedException ex) {
385: String mes = NbBundle.getMessage(
386: JaxRpcClientCreator.class,
387: "ERR_TempFileLocked",
388: sourceWsdlFileTmp
389: .getNameExt()); // NOI18N
390: NotifyDescriptor desc = new NotifyDescriptor.Message(
391: mes,
392: NotifyDescriptor.Message.ERROR_MESSAGE);
393: DialogDisplayer.getDefault()
394: .notify(desc);
395: } catch (IOException ex) {
396: String mes = NbBundle.getMessage(
397: JaxRpcClientCreator.class,
398: "ERR_TempFileNotDeleted",
399: sourceWsdlFileTmp
400: .getNameExt()); // NOI18N
401: NotifyDescriptor desc = new NotifyDescriptor.Message(
402: mes,
403: NotifyDescriptor.Message.ERROR_MESSAGE);
404: DialogDisplayer.getDefault()
405: .notify(desc);
406: }
407: }
408:
409: handle.progress(NbBundle.getMessage(
410: JaxRpcClientCreator.class,
411: "MSG_WizDone"), 99);
412: } finally {
413: handle.finish();
414: }
415: }
416: });
417: }
418:
419: /**
420: * Returns Java source groups for all source packages in given project.<br>
421: * Doesn't include test packages.
422: *
423: * @param project Project to search
424: * @return Array of SourceGroup. It is empty if any probelm occurs.
425: */
426: static SourceGroup[] getJavaSourceGroups(Project project) {
427: SourceGroup[] sourceGroups = ProjectUtils
428: .getSources(project)
429: .getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
430: Set testGroups = getTestSourceGroups(project, sourceGroups);
431: List result = new ArrayList();
432: for (int i = 0; i < sourceGroups.length; i++) {
433: if (!testGroups.contains(sourceGroups[i])) {
434: result.add(sourceGroups[i]);
435: }
436: }
437: return (SourceGroup[]) result.toArray(new SourceGroup[result
438: .size()]);
439: }
440:
441: private static Set/*<SourceGroup>*/getTestSourceGroups(
442: Project project, SourceGroup[] sourceGroups) {
443: Map foldersToSourceGroupsMap = createFoldersToSourceGroupsMap(sourceGroups);
444: Set testGroups = new HashSet();
445: for (int i = 0; i < sourceGroups.length; i++) {
446: testGroups.addAll(getTestTargets(sourceGroups[i],
447: foldersToSourceGroupsMap));
448: }
449: return testGroups;
450: }
451:
452: private static List/*<SourceGroup>*/getTestTargets(
453: SourceGroup sourceGroup, Map foldersToSourceGroupsMap) {
454: final URL[] rootURLs = UnitTestForSourceQuery
455: .findUnitTests(sourceGroup.getRootFolder());
456: if (rootURLs.length == 0) {
457: return new ArrayList();
458: }
459: List result = new ArrayList();
460: List sourceRoots = getFileObjects(rootURLs);
461: for (int i = 0; i < sourceRoots.size(); i++) {
462: FileObject sourceRoot = (FileObject) sourceRoots.get(i);
463: SourceGroup srcGroup = (SourceGroup) foldersToSourceGroupsMap
464: .get(sourceRoot);
465: if (srcGroup != null) {
466: result.add(srcGroup);
467: }
468: }
469: return result;
470: }
471:
472: private static Map createFoldersToSourceGroupsMap(
473: final SourceGroup[] sourceGroups) {
474: Map result;
475: if (sourceGroups.length == 0) {
476: result = Collections.EMPTY_MAP;
477: } else {
478: result = new HashMap(2 * sourceGroups.length, .5f);
479: for (int i = 0; i < sourceGroups.length; i++) {
480: SourceGroup sourceGroup = sourceGroups[i];
481: result.put(sourceGroup.getRootFolder(), sourceGroup);
482: }
483: }
484: return result;
485: }
486:
487: private static List/*<FileObject>*/getFileObjects(URL[] urls) {
488: List result = new ArrayList();
489: for (int i = 0; i < urls.length; i++) {
490: FileObject sourceRoot = URLMapper.findFileObject(urls[i]);
491: if (sourceRoot != null) {
492: result.add(sourceRoot);
493: } else {
494: int severity = ErrorManager.INFORMATIONAL;
495: if (ErrorManager.getDefault().isNotifiable(severity)) {
496: ErrorManager.getDefault().notify(
497: severity,
498: new IllegalStateException(
499: "No FileObject found for the following URL: "
500: + urls[i])); //NOI18N
501: }
502: }
503: }
504: return result;
505: }
506:
507: private J2eePlatform getJ2eePlatform() {
508: J2eeModuleProvider provider = (J2eeModuleProvider) project
509: .getLookup().lookup(J2eeModuleProvider.class);
510: if (provider != null) {
511: String serverInstanceID = provider.getServerInstanceID();
512: if (serverInstanceID != null
513: && serverInstanceID.length() > 0) {
514: return Deployment.getDefault().getJ2eePlatform(
515: serverInstanceID);
516: }
517: }
518: return null;
519: }
520:
521: private boolean isJWSDPSupported() {
522: J2eePlatform j2eePlatform = getJ2eePlatform();
523: if (j2eePlatform != null) {
524: return j2eePlatform
525: .isToolSupported(J2eePlatform.TOOL_JWSDP);
526: }
527: return false;
528: }
529:
530: private boolean isJsr109Supported() {
531: J2eePlatform j2eePlatform = getJ2eePlatform();
532: if (j2eePlatform != null) {
533: return j2eePlatform
534: .isToolSupported(J2eePlatform.TOOL_JSR109);
535: }
536: return false;
537: }
538:
539: private boolean isJsr109OldSupported() {
540: J2eePlatform j2eePlatform = getJ2eePlatform();
541: if (j2eePlatform != null) {
542: return j2eePlatform
543: .isToolSupported(J2eePlatform.TOOL_WSCOMPILE);
544: }
545: return false;
546: }
547:
548: /**
549: *
550: * <b>DON'T USE</b>, for tests only
551: */
552: Task task;
553: }
|