blob: 757d67ddd11c3cdd2dca23e452a0f3d7a4ed6456 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.websvc.spi.jaxws.client;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.SwingUtilities;
import org.apache.tools.ant.module.api.support.ActionUtils;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectManager;
import org.netbeans.modules.websvc.api.jaxws.project.CatalogUtils;
import org.netbeans.modules.websvc.api.jaxws.project.JAXWSVersionProvider;
import org.netbeans.modules.websvc.api.jaxws.project.config.Client;
import org.netbeans.modules.websvc.api.jaxws.project.config.ClientAlreadyExistsExeption;
import org.netbeans.modules.websvc.api.jaxws.project.config.JaxWsModel;
import org.netbeans.modules.websvc.api.jaxws.project.WSUtils;
import org.netbeans.modules.websvc.api.jaxws.project.config.WsimportOption;
import org.netbeans.modules.websvc.api.jaxws.project.config.WsimportOptions;
import org.netbeans.modules.websvc.api.jaxws.wsdlmodel.WsdlModel;
import org.netbeans.modules.websvc.api.jaxws.wsdlmodel.WsdlModelListener;
import org.netbeans.modules.websvc.api.jaxws.wsdlmodel.WsdlModeler;
import org.netbeans.modules.websvc.api.jaxws.wsdlmodel.WsdlModelerFactory;
import org.netbeans.modules.websvc.api.jaxws.wsdlmodel.WsdlService;
import org.netbeans.spi.project.support.ant.AntProjectHelper;
import org.netbeans.spi.project.support.ant.GeneratedFilesHelper;
import org.openide.DialogDisplayer;
import org.openide.ErrorManager;
import org.openide.NotifyDescriptor;
import org.openide.execution.ExecutorTask;
import org.openide.filesystems.FileLock;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileStateInvalidException;
import org.openide.filesystems.FileUtil;
import org.openide.nodes.Node;
import org.openide.util.Mutex;
import org.openide.util.MutexException;
import org.openide.util.NbBundle;
import org.openide.util.RequestProcessor;
import org.openide.windows.TopComponent;
import org.openide.windows.WindowManager;
/**
*
* @author mkuchtiak
*/
public abstract class ProjectJAXWSClientSupport implements JAXWSClientSupportImpl {
private static final String[] DEFAULT_WSIMPORT_OPTIONS = {"extension", "verbose", "fork"}; //NOI18N
private static final String[] DEFAULT_WSIMPORT_VALUES = {"true", "true", "false"}; //NOI18N
private static final String XNOCOMPILE_OPTION = "xnocompile"; //NOI18N
private static final String XENDORSED_OPTION = "xendorsed"; //NOI18N
private static final String PACKAGE_OPTION = "package"; //NOI18N
private static final String WSDL_LOCATION_OPTION = "wsdlLocation"; //NOI18N
private static final String TARGET_OPTION = "target"; //NOI18N
protected static final String JAVA_EE_VERSION_NONE="java-ee-version-none"; //NOI18N
protected static final String JAVA_EE_VERSION_15="java-ee-version-15"; //NOI18N
protected static final String JAVA_EE_VERSION_16="java-ee-version-16"; //NOI18N
protected static final String JAVA_EE_VERSION_17="java-ee-version-17"; //NOI18N
protected static final String JAVA_EE_VERSION_18="java-ee-version-18";
protected static final String JAKARTA_EE_VERSION_8="jakarta-ee-version-8"; //NOI18N
protected static final String JAKARTA_EE_VERSION_9="jakarta-ee-version-9"; //NOI18N
protected static final String JAKARTA_EE_VERSION_91="jakarta-ee-version-91"; //NOI18N
protected static final String JAKARTA_EE_VERSION_10="jakarta-ee-version-10"; //NOI18N
Project project;
private AntProjectHelper helper;
private FileObject clientArtifactsFolder;
/** Creates a new instance of WebProjectJAXWSClientSupport */
public ProjectJAXWSClientSupport(Project project, AntProjectHelper helper ) {
this.project=project;
this.helper = helper;
}
public void removeServiceClient(String serviceName) {
JaxWsModel jaxWsModel = project.getLookup().lookup(JaxWsModel.class);
if (jaxWsModel!=null && jaxWsModel.removeClient(serviceName)) {
writeJaxWsModel(jaxWsModel);
}
}
public AntProjectHelper getAntProjectHelper() {
return helper;
}
public String getWsdlUrl(String serviceName) {
JaxWsModel jaxWsModel = project.getLookup().lookup(JaxWsModel.class);
if (jaxWsModel!=null) {
Client client = jaxWsModel.findClientByName(serviceName);
if (client!=null) return client.getWsdlUrl();
}
return null;
}
public String addServiceClient(String clientName, String wsdlUrl, String packageName, boolean isJsr109) {
// create jax-ws.xml if necessary
FileObject fo = WSUtils.findJaxWsFileObject(project);
if (fo==null) {
try {
WSUtils.createJaxWsFileObject(project);
} catch (IOException ex) {
ErrorManager.getDefault().notify(ex);
}
}
final JaxWsModel jaxWsModel = project.getLookup().lookup(JaxWsModel.class);
String finalClientName=clientName;
boolean clientAdded=false;
if (jaxWsModel!=null) {
if(!isJsr109){
try{
addJaxWs20Library();
} catch(Exception e){ //TODO handle this
ErrorManager.getDefault().notify(e);
}
}
Client client=null;
finalClientName = findProperClientName(clientName, jaxWsModel);
FileObject xmlResourcesFo = getLocalWsdlFolderForClient(finalClientName,true);
FileObject localWsdl=null;
try {
localWsdl = WSUtils.retrieveResource(
xmlResourcesFo,
new URI(wsdlUrl));
} catch (URISyntaxException ex) {
ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
String mes = NbBundle.getMessage(ProjectJAXWSClientSupport.class, "ERR_IncorrectURI", wsdlUrl); // NOI18N
NotifyDescriptor desc = new NotifyDescriptor.Message(mes, NotifyDescriptor.Message.ERROR_MESSAGE);
DialogDisplayer.getDefault().notify(desc);
} catch (UnknownHostException ex) {
ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
String mes = NbBundle.getMessage(ProjectJAXWSClientSupport.class, "ERR_UnknownHost", ex.getMessage()); // NOI18N
NotifyDescriptor desc = new NotifyDescriptor.Message(mes, NotifyDescriptor.Message.ERROR_MESSAGE);
DialogDisplayer.getDefault().notify(desc);
} catch (IOException ex) {
ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
String mes = NbBundle.getMessage(ProjectJAXWSClientSupport.class, "ERR_WsdlRetrieverFailure", wsdlUrl); // NOI18N
NotifyDescriptor desc = new NotifyDescriptor.Message(mes, NotifyDescriptor.Message.ERROR_MESSAGE);
DialogDisplayer.getDefault().notify(desc);
}
if (localWsdl!=null) {
try {
String localWsdlUrl = FileUtil.getRelativePath(xmlResourcesFo, localWsdl);
client = jaxWsModel.addClient(finalClientName, wsdlUrl, packageName);
client.setLocalWsdlFile(localWsdlUrl);
if (packageName == null) {
// compute package name from namespace
client.setPackageName(
WSUtils.getPackageNameForWsdl(FileUtil.toFile(localWsdl)));
}
} catch (ClientAlreadyExistsExeption ex) {
//this shouldn't happen
}
FileObject catalog = getCatalogFileObject();
if (catalog!=null) client.setCatalogFile(CATALOG_FILE);
WsimportOptions wsimportOptions = client.getWsImportOptions();
WsimportOption wsimportOption = null;
if (wsimportOptions != null) {
int i=0;
for (String option:DEFAULT_WSIMPORT_OPTIONS) {
wsimportOption = wsimportOptions.newWsimportOption();
wsimportOption.setWsimportOptionName(option);
wsimportOption.setWsimportOptionValue(DEFAULT_WSIMPORT_VALUES[i++]); //NOI18N
wsimportOptions.addWsimportOption(wsimportOption);
}
wsimportOption = wsimportOptions.newWsimportOption();
wsimportOption.setWsimportOptionName(WSDL_LOCATION_OPTION);
wsimportOption.setWsimportOptionValue(wsdlUrl);
wsimportOptions.addWsimportOption(wsimportOption);
if (isXnocompile(project)) {
wsimportOption = wsimportOptions.newWsimportOption();
wsimportOption.setWsimportOptionName(XNOCOMPILE_OPTION);
wsimportOption.setWsimportOptionValue("true"); //NOI18N
wsimportOptions.addWsimportOption(wsimportOption);
}
if (isXendorsed(project)) {
wsimportOption = wsimportOptions.newWsimportOption();
wsimportOption.setWsimportOptionName(XENDORSED_OPTION);
wsimportOption.setWsimportOptionValue("true"); //NOI18N
wsimportOptions.addWsimportOption(wsimportOption);
}
if (packageName != null) {
wsimportOption = wsimportOptions.newWsimportOption();
wsimportOption.setWsimportOptionName(PACKAGE_OPTION);
wsimportOption.setWsimportOptionValue(packageName); //NOI18N
wsimportOptions.addWsimportOption(wsimportOption);
}
if (JAVA_EE_VERSION_15.equals(getProjectJavaEEVersion())) {
wsimportOption = wsimportOptions.newWsimportOption();
wsimportOption.setWsimportOptionName(TARGET_OPTION);
wsimportOption.setWsimportOptionValue("2.1"); //NOI18N
wsimportOptions.addWsimportOption(wsimportOption);
}
}
writeJaxWsModel(jaxWsModel);
clientAdded=true;
// get jax-ws-catalog.xml
if (catalog != null) {
try {
FileObject webInfWsdl = getWsdlFolder(true);
if (webInfWsdl != null) {
FileObject jaxWsCatalog = webInfWsdl.getParent().getFileObject("jax-ws-catalog.xml");
if (jaxWsCatalog == null) {
jaxWsCatalog = FileUtil.copyFile(catalog, webInfWsdl.getParent(), "jax-ws-catalog"); //NOI18N
// update system elements in jax-ws-catalog.xml
CatalogUtils.updateCatalogEntriesForClient(jaxWsCatalog, clientName);
} else {
// copy, and modify catalog entries from catalog.xml to jax-ws-catalog.xml
CatalogUtils.copyCatalogEntriesForClient(catalog, jaxWsCatalog, clientName);
}
// copy files
WSUtils.copyFiles(xmlResourcesFo, webInfWsdl);
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
// generate wsdl model immediately
final String clientName2 = finalClientName;
final WsdlModeler modeler = WsdlModelerFactory.getDefault().getWsdlModeler(localWsdl.toURL());
if (modeler!=null) {
modeler.setPackageName(packageName);
if (catalog != null) {
modeler.setCatalog(catalog.toURL());
}
modeler.generateWsdlModel(new WsdlModelListener() {
public void modelCreated(WsdlModel model) {
if (model==null) {
RequestProcessor.getDefault().post(new Runnable() {
public void run() {
DialogDisplayer.getDefault().notify(new WsImportFailedMessage(modeler.getCreationException()));
}
});
} else {
Client client = jaxWsModel.findClientByName(clientName2);
String packName = client.getPackageName();
// this shuldn't normally happen
// this applies only for case when package name cannot be resolved for namespace
if (packName == null) {
if (model.getServices().size() > 0) {
WsdlService service = model.getServices().get(0);
String javaName = service.getJavaName();
int index = javaName.lastIndexOf(".");
if (index != -1){
packName = javaName.substring(0,index );
} else {
packName = javaName;
}
client.setPackageName(packName);
writeJaxWsModel(jaxWsModel);
}
}
runWsimport(clientName2);
}
}
});
}
}
return finalClientName;
}
return null;
}
private void runWsimport(String finalClientName){
final FileObject buildImplFo = project.getProjectDirectory().getFileObject(GeneratedFilesHelper.BUILD_XML_PATH);
final String finalName = finalClientName;
if (SwingUtilities.isEventDispatchThread()) {
openOutputWindow();
} else {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
openOutputWindow();
}
});
}
try {
ProjectManager.mutex().readAccess(new Mutex.ExceptionAction<Boolean>() {
public Boolean run() throws IOException {
Properties props = WSUtils.identifyWsimport(helper);
ExecutorTask wsimportTask =
ActionUtils.runTarget(buildImplFo,new String[]{"wsimport-client-"+finalName},props); //NOI18N
return Boolean.TRUE;
}
});
} catch (MutexException e) {
ErrorManager.getDefault().notify(e);
}
}
private void openOutputWindow() {
TopComponent outputTc = WindowManager.getDefault().findTopComponent("output"); //NOI18N
if (outputTc != null) {
outputTc.open();
}
}
private String findProperClientName(String name, JaxWsModel jaxWsModel) {
String firstName=name.length()==0?NbBundle.getMessage(ProjectJAXWSClientSupport.class,"LBL_defaultClientName"):name;
if (jaxWsModel.findClientByName(firstName)==null) return firstName;
for (int i = 1;; i++) {
String finalName = firstName + "_" + i; // NOI18N
if (jaxWsModel.findClientByName(finalName)==null)
return finalName;
}
}
private void writeJaxWsModel(JaxWsModel jaxWsModel) {
try {
jaxWsModel.write();
} catch (IOException ex) {
Logger.getLogger(this.getClass().getName()).log(Level.FINE, "failed to save jax-ws.xml", ex); //NOI18N
}
}
public List<Client> getServiceClients() {
List<Client> jaxWsClients = new ArrayList<>();
JaxWsModel jaxWsModel = project.getLookup().lookup(JaxWsModel.class);
if (jaxWsModel!=null) {
Client[] clients = jaxWsModel.getClients();
for (int i=0;i<clients.length;i++) jaxWsClients.add(clients[i]);
}
return jaxWsClients;
}
/**
* return root folder for wsdl artifacts
*/
public FileObject getLocalWsdlFolderForClient(String clientName, boolean createFolder) {
return getArtifactsFolder(clientName, createFolder, true);
}
/**
* return folder for local wsdl bindings
*/
public FileObject getBindingsFolderForClient(String clientName, boolean createFolder) {
return getArtifactsFolder(clientName, createFolder, false);
}
private FileObject getArtifactsFolder(String clientName, boolean createFolder, boolean forWsdl) {
String folderName = forWsdl?"wsdl":"bindings"; //NOI18N
FileObject root = getXmlArtifactsRoot();
assert root!=null;
FileObject wsdlLocalFolder = root.getFileObject(XML_RESOURCES_FOLDER+"/"+CLIENTS_LOCAL_FOLDER+"/"+clientName+"/"+folderName); //NOI18N
if (wsdlLocalFolder==null && createFolder) {
try {
FileObject xmlLocalFolder = root.getFileObject(XML_RESOURCES_FOLDER);
if (xmlLocalFolder==null) xmlLocalFolder = root.createFolder(XML_RESOURCES_FOLDER);
FileObject servicesLocalFolder = xmlLocalFolder.getFileObject(CLIENTS_LOCAL_FOLDER);
if (servicesLocalFolder==null) servicesLocalFolder = xmlLocalFolder.createFolder(CLIENTS_LOCAL_FOLDER);
FileObject serviceLocalFolder = servicesLocalFolder.getFileObject(clientName);
if (serviceLocalFolder==null) serviceLocalFolder = servicesLocalFolder.createFolder(clientName);
wsdlLocalFolder=serviceLocalFolder.getFileObject(folderName);
if (wsdlLocalFolder==null) wsdlLocalFolder = serviceLocalFolder.createFolder(folderName);
} catch (IOException ex) {
return null;
}
}
return wsdlLocalFolder;
}
/** return root folder for xml artifacts
*/
protected FileObject getXmlArtifactsRoot() {
return project.getProjectDirectory();
}
private FileObject getCatalogFileObject() {
return project.getProjectDirectory().getFileObject(CATALOG_FILE);
}
public URL getCatalog() {
FileObject catalog = getCatalogFileObject();
return ((catalog==null) ? null : catalog.toURL());
}
protected abstract void addJaxWs20Library() throws Exception;
public abstract FileObject getWsdlFolder(boolean create) throws IOException;
public String getServiceRefName(Node clientNode) {
WsdlService service = clientNode.getLookup().lookup(WsdlService.class);
String serviceName = service.getName();
return "service/" + serviceName;
}
private class WsImportFailedMessage extends NotifyDescriptor.Message {
public WsImportFailedMessage(Throwable ex) {
super(NbBundle.getMessage(ProjectJAXWSClientSupport.class,"TXT_CannotGenerateClient",ex.getLocalizedMessage()),
NotifyDescriptor.ERROR_MESSAGE);
}
}
/** folder where xml client artifacts should be saved, e.g. WEB-INF/wsdl/client/SampleClient
*/
protected FileObject getWsdlFolderForClient(String name) throws IOException {
FileObject globalWsdlFolder = getWsdlFolder(true);
FileObject oldWsdlFolder = globalWsdlFolder.getFileObject("client/"+name); //NOI18N
if (oldWsdlFolder!=null) {
FileLock lock = oldWsdlFolder.lock();
try {
oldWsdlFolder.delete(lock);
} finally {
lock.releaseLock();
}
}
FileObject clientWsdlFolder = globalWsdlFolder.getFileObject("client"); //NOI18N
if (clientWsdlFolder==null) clientWsdlFolder = globalWsdlFolder.createFolder("client"); //NOI18N
return clientWsdlFolder.createFolder(name);
}
private static boolean isXnocompile(Project project){
JAXWSVersionProvider jvp = project.getLookup().lookup(JAXWSVersionProvider.class);
if (jvp != null) {
String version = jvp.getJAXWSVersion();
if (version != null) {
return isVersionSatisfied(version, "2.1.3");
}
}
// Defaultly return true
return true;
}
private static boolean isXendorsed(Project project){
JAXWSVersionProvider jvp = project.getLookup().lookup(JAXWSVersionProvider.class);
if (jvp != null) {
String version = jvp.getJAXWSVersion();
if (version != null) {
return isVersionSatisfied(version, "2.1.1"); //NOI18N
}
}
// Defaultly return false
return false;
}
private static boolean isVersionSatisfied(String version, String requiredVersion) {
int len1 = version.length();
int len2 = requiredVersion.length();
for (int i=0;i<Math.min(len1, len2);i++) {
if (version.charAt(i) < requiredVersion.charAt(i)) {
return false;
} else if (version.charAt(i) > requiredVersion.charAt(i)) {
return true;
}
}
if (len1 > len2) return true;
else if (len1 < len2) return false;
return true;
}
protected String getProjectJavaEEVersion() {
return JAVA_EE_VERSION_NONE;
}
}