/****************************************************************************** * Copyright (c) 2010-2013, Linagora * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Linagora - initial API and implementation *******************************************************************************/ package com.ebmwebsourcing.petals.services.jsr181.handlers; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.net.URI; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.actions.WorkspaceModifyOperation; import org.eclipse.ui.progress.IProgressService; import com.ebmwebsourcing.petals.common.generation.JbiXmlGenerationHelper; import com.ebmwebsourcing.petals.common.generation.cdk5.components.Jsr181Provides1x; import com.ebmwebsourcing.petals.common.internal.provisional.utils.JaxWsUtils; import com.ebmwebsourcing.petals.common.internal.provisional.utils.JaxWsUtils.JaxWsException; import com.ebmwebsourcing.petals.common.internal.provisional.utils.PetalsConstants; import com.ebmwebsourcing.petals.common.internal.provisional.utils.ResourceUtils; import com.ebmwebsourcing.petals.common.internal.provisional.utils.WsdlUtils; import com.ebmwebsourcing.petals.common.internal.provisional.utils.WsdlUtils.JbiBasicBean; import com.ebmwebsourcing.petals.services.jsr181.PetalsJsr181Plugin; import com.ebmwebsourcing.petals.services.utils.PetalsServicesProjectUtils; /** * @author Vincent Zurczak - EBM WebSourcing */ public class Jsr181GenerationHandler extends AbstractHandler { /* * (non-Javadoc) * @see org.eclipse.core.commands.AbstractHandler * #execute(org.eclipse.core.commands.ExecutionEvent) */ @Override public Object execute( final ExecutionEvent event ) throws ExecutionException { final IJavaProject javaProject = getSelectedJavaProject(); if( javaProject != null ) { // Need for a confirmation? String msg = "Would you like to generate a new jbi.xml file right after the WSDL generation?\n" + "This jbi.xml will rely on all the generated WSDL definitions.\n\n" + "Please, note this will overwrite the existing one."; final boolean generateJbiXml = MessageDialog.openQuestion( new Shell(), "Also generate a new jbi.xml?", msg ); // Define the generation context WorkspaceModifyOperation op = new WorkspaceModifyOperation() { @Override protected void execute( IProgressMonitor monitor ) throws CoreException, InterruptedException { try { monitor.beginTask( "Generating Petals required files...", IProgressMonitor.UNKNOWN ); generateJsr181Files( javaProject, generateJbiXml, monitor ); } finally { monitor.done(); } } }; // Run it try { IProgressService ps = PlatformUI.getWorkbench().getProgressService(); ps.busyCursorWhile( op ); } catch( InterruptedException e ) { // nothing } catch( InvocationTargetException e ) { PetalsJsr181Plugin.log( e, IStatus.ERROR, "A problem occurred while generating files for the JSR-181." ); MessageDialog.openError( new Shell(), "Generation Error", "A problem occurred while generating files for the JSR-181.\nCheck the log for more details." ); } } return null; } /** * Updates the handler state from the current selection. * @return the first selected SU Java project, or null if the selection is not a SU Java project */ private IJavaProject getSelectedJavaProject() { IJavaProject javaProject = null; try { final ISelection selection = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getSelection(); Object o; if( selection instanceof IStructuredSelection && ! selection.isEmpty() && ( o = ((IStructuredSelection) selection).getFirstElement()) instanceof IProject) { IProject p = (IProject) o; if( p.isAccessible() && p.hasNature( JavaCore.NATURE_ID ) && "petals-se-jsr181".equalsIgnoreCase( PetalsServicesProjectUtils.getComponentName( p ))) javaProject = JavaCore.create( p ); } } catch( CoreException e ) { PetalsJsr181Plugin.log( e, IStatus.WARNING ); } catch( Exception e ) { PetalsJsr181Plugin.log( e, IStatus.WARNING ); } return javaProject; } /** * Generates files for the JSR-181. * <p> * 1. All the WSDL and XML schemas are deleted from the "jbi" directory.<br /> * 2. Are listed all the classes contained in the project and annotated @WebService.<br /> * 3. For each annotated class, a WSDL is generated in the "jbi" directory.<br /> * 4. Eventually, if the option is activated, a jbi.xml is generated from all the WSDL. * </p> * * @param javaProject * @param generateJbiXml * @param monitor * @throws CoreException */ public static void generateJsr181Files( IJavaProject javaProject, boolean generateJbiXml, IProgressMonitor monitor ) throws CoreException { // Delete all the WSDL and XSD files from the "jbi" directory IFolder jbiFolder = javaProject.getProject().getFolder( PetalsConstants.LOC_RES_FOLDER ); javaProject.getProject().refreshLocal( IResource.DEPTH_INFINITE, monitor ); for( IResource res : jbiFolder.members()) { if( res instanceof IFile && ( res.getName().endsWith( ".wsdl" ) || res.getName().endsWith( ".xsd" ))) res.delete( true, monitor ); } // Get the classes that contain a JAX annotated service Map<String,String> classNameToServiceName = JaxWsUtils.getJaxAnnotatedJavaTypes( javaProject, monitor, true, false ); // Create the WSDL Map<String,String> classNameToWsdlName = new HashMap<String,String>( classNameToServiceName.size()); File targetDirectory = jbiFolder.getLocation().toFile(); int generationErrorsCpt = 0; for( Map.Entry<String,String> entry : classNameToServiceName.entrySet()) { try { if( monitor != null && monitor.isCanceled()) throw new OperationCanceledException(); JaxWsUtils.INSTANCE.generateWsdl( entry.getKey(), targetDirectory, javaProject ); // Only store those whose were generated without error classNameToWsdlName.put( entry.getKey(), entry.getValue() + ".wsdl" ); } catch( IOException e ) { PetalsJsr181Plugin.log( e, IStatus.ERROR ); } catch( InterruptedException e ) { PetalsJsr181Plugin.log( e, IStatus.ERROR ); } catch( JaxWsException e ) { generationErrorsCpt ++; PetalsJsr181Plugin.log( e, IStatus.ERROR ); } } jbiFolder.refreshLocal( IResource.DEPTH_INFINITE, monitor ); // Generate the jbi.xml? if( generateJbiXml ) generateJbiXml( javaProject.getProject(), classNameToWsdlName, monitor ); ResourceUtils.selectResourceInPetalsExplorer( true, jbiFolder ); // Report errors if( generationErrorsCpt != 0 ) { final String msg = generationErrorsCpt + (generationErrorsCpt > 1 ? " errors" : " error") + " occurred during the generation process.\nCheck the log for more details."; Display.getDefault().asyncExec( new Runnable() { @Override public void run() { MessageDialog.openError( new Shell(), "Generation Error", msg ); } }); } } /** * Generates the jbi.xml from the WSDL in the project. * * @param project the SU project * @param classNameToWsdlName map that associated a class name and a WSDL * <p> * Key = the qualified name of the annotated class<br /> * Value = the WSDL file name * </p> * * @param monitor the progress monitor * @throws CoreException if the project resources could not be manipulated */ public static void generateJbiXml( IProject project, Map<String,String> classNameToWsdlName, IProgressMonitor monitor ) throws CoreException { // Get the generation values List<Jsr181Provides1x> provides = new ArrayList<Jsr181Provides1x> (); for( Map.Entry<String,String> entry : classNameToWsdlName.entrySet()) { IFile wsdlFile = project.getFolder( PetalsConstants.LOC_RES_FOLDER ).getFile( entry.getValue()); if( wsdlFile.exists()) { URI uri = wsdlFile.getLocation().toFile().toURI(); try { List<JbiBasicBean> beans = WsdlUtils.INSTANCE.parse( uri ); for( JbiBasicBean bean : beans ) { Jsr181Provides1x jsr181Bean = new Jsr181Provides1x(); jsr181Bean.setEndpointName( bean.getEndpointName()); jsr181Bean.setServiceName( bean.getServiceName().getLocalPart()); jsr181Bean.setServiceNamespace( bean.getServiceName().getNamespaceURI()); jsr181Bean.setInterfaceName( bean.getInterfaceName().getLocalPart()); jsr181Bean.setInterfaceNamespace( bean.getInterfaceName().getNamespaceURI()); jsr181Bean.setWsdl( entry.getValue()); jsr181Bean.setClassName( entry.getKey()); provides.add( jsr181Bean ); } } catch( InvocationTargetException e ) { // nothing } } } // Generate and write the jbi.xml JbiXmlGenerationHelper genDelegate = new JbiXmlGenerationHelper(); genDelegate.setComponentName( "petals-se-jsr181" ); Jsr181Provides1x[] bps = new Jsr181Provides1x[ provides.size()]; String jbiXmlContent = genDelegate.createJbiDescriptor( provides.toArray( bps )).toString(); IFile jbiXmlFile = project.getFile( PetalsConstants.LOC_JBI_FILE ); if( ! jbiXmlFile.exists()) jbiXmlFile.create( new ByteArrayInputStream( jbiXmlContent.getBytes()), true, monitor ); else jbiXmlFile.setContents( new ByteArrayInputStream( jbiXmlContent.getBytes()), true, true, monitor ); } }