/****************************************************************************** * Copyright (c) 2008-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.common.internal.provisional.utils; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.StringWriter; import java.net.URI; import java.util.HashMap; import java.util.Map; import javax.xml.parsers.ParserConfigurationException; import org.eclipse.bpel.common.wsdl.helpers.UriAndUrlHelper; 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.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.emf.common.util.BasicEList; import org.eclipse.emf.common.util.Diagnostic; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.EMap; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.resource.URIConverter; import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.emf.ecore.util.FeatureMap; import org.eclipse.emf.ecore.util.FeatureMapUtil; import org.eclipse.emf.ecore.xmi.XMLResource; import org.eclipse.emf.ecore.xmi.impl.DefaultDOMHandlerImpl; import org.eclipse.emf.ecore.xml.type.AnyType; import org.w3c.dom.Document; import org.xml.sax.SAXException; import com.ebmwebsourcing.petals.common.internal.PetalsCommonPlugin; import com.ebmwebsourcing.petals.common.internal.provisional.emf.InvalidJbiXmlException; import com.ebmwebsourcing.petals.common.internal.provisional.emf.JbiCustomDiagnostician; import com.sun.java.xml.ns.jbi.Consumes; import com.sun.java.xml.ns.jbi.DocumentRoot; import com.sun.java.xml.ns.jbi.Jbi; import com.sun.java.xml.ns.jbi.Provides; import com.sun.java.xml.ns.jbi.util.JbiResourceFactoryImpl; /** * @author Vincent Zurczak - EBM WebSourcing */ public final class JbiXmlUtils { /** * Private constructor for utility class. */ private JbiXmlUtils() { // nothing } /** * Writes a {@link Jbi} instance into a file. * @param jbiInstance the JBI instance to write * @param targetFile the target file * @param saveOptions the save options * @throws IOException if the content could not be saved */ public static void writeJbiXmlModel( Jbi jbiInstance, File targetFile, Map<?,?> saveOptions ) throws IOException { org.eclipse.emf.common.util.URI emfUri = org.eclipse.emf.common.util.URI.createFileURI( targetFile.getAbsolutePath()); Resource resource = new JbiResourceFactoryImpl().createResource( emfUri ); resource.getContents().add( EcoreUtil.copy( jbiInstance )); // Copy because of EMF transactions resource.save( saveOptions ); } /** * Writes a {@link Jbi} instance into a file. * @param jbiInstance the JBI instance to write * @param targetFile the target file * @throws IOException if the content could not be saved */ public static void writeJbiXmlModel( Jbi jbiInstance, File targetFile ) throws IOException { writeJbiXmlModel( jbiInstance, targetFile, getJbiXmlSaveOptions()); } /** * Writes a portion of a {@link Jbi} instance and returns it as a string. * @param object the EObject * @return the serialized content of the EObject * @throws IOException */ public static String writePartialJbiXmlModel( EObject object ) throws IOException { Map<Object,Object> options = getJbiXmlSaveOptions(); EList<EObject> roots = new BasicEList<EObject> (); roots.add( object ); options.put( XMLResource.OPTION_ROOT_OBJECTS, roots ); options.put( XMLResource.OPTION_DECLARE_XML, false ); StringWriter sw = new StringWriter(); URIConverter.WriteableOutputStream uws = new URIConverter.WriteableOutputStream( sw, "UTF-8" ); object.eResource().save( uws, options ); return sw.toString(); } /** * Writes a portion of a {@link Jbi} instance and returns it as a document. * @param object the EObject * @return the created document, or null if it could not be created */ public static Document savePartialJbiXmlAsDocument( EObject object ) { Document doc = null; try { String s = writePartialJbiXmlModel( object ); doc = DomUtils.buildDocument( s ); } catch( IOException e ) { PetalsCommonPlugin.log( e, IStatus.ERROR ); } catch( SAXException e ) { PetalsCommonPlugin.log( e, IStatus.ERROR ); } catch( ParserConfigurationException e ) { PetalsCommonPlugin.log( e, IStatus.ERROR ); } return doc; } /** * Writes a {@link Jbi} instance into a file. * @param jbiInstance the JBI instance to write * @return the created document, or null if it could not be created */ public static Document saveJbiXmlAsDocument( Jbi jbiInstance ) { return saveJbiXmlAsDocument( jbiInstance, getJbiXmlSaveOptions()); } /** * Writes an EObject instance into a file. * @param eo the EObject to write * @return the created document, or null if it could not be created */ public static Document saveJbiXmlAsDocument( EObject eo, Map<?,?> saveOptions ) { Document doc = null; try { doc = DomUtils.buildNewDocument(); XMLResource resource = (XMLResource) new JbiResourceFactoryImpl().createResource( null ); resource.getContents().add( EcoreUtil.copy( eo )); // Copy because of EMF transactions resource.save( doc, saveOptions, new DefaultDOMHandlerImpl()); } catch( Exception e ) { PetalsCommonPlugin.log( e, IStatus.ERROR ); } return doc; } /** * @return the save options for jbi.xml files */ public static Map<Object,Object> getJbiXmlSaveOptions() { Map<Object,Object> options = new HashMap<Object,Object> (); options.put( XMLResource.OPTION_ENCODING, "UTF-8" ); options.put( XMLResource.OPTION_ESCAPE_USING_CDATA, Boolean.TRUE ); options.put( XMLResource.OPTION_EXTENDED_META_DATA, Boolean.TRUE ); // FIXME: are the following ones required? // options.put(XMLResource.OPTION_XML_MAP, xmlMap); return options; } /** * @return the load options for jbi.xml files */ public static Map<Object,Object> getJbiXmlLoadOptions() { Map<Object,Object> options = new HashMap<Object,Object> (); options.put( XMLResource.OPTION_ENCODING, "UTF-8" ); options.put( XMLResource.OPTION_EXTENDED_META_DATA, Boolean.TRUE ); options.put( XMLResource.OPTION_USE_LEXICAL_HANDLER, Boolean.TRUE ); return options; } /** * Finds the map associating name spaces and prefixes in the EMF model. * @param eo an EObject * @return the map, or null if the document root could not be found */ public static EMap<String,String> findPrefixMap( EObject eo ) { EMap<String,String> result = null; EObject cur = eo; while( cur != null && ! ( cur instanceof DocumentRoot )) cur = cur.eContainer(); if( cur != null ) result = ((DocumentRoot) cur).getXMLNSPrefixMap(); return result; } /** * Writes a {@link Jbi} instance into a file. * @param jbiInstance the JBI instance to write * @param targetFile the target file * @throws IOException if the content could not be saved */ public static void writeJbiXmlModel( Jbi jbiInstance, IFile targetFile ) throws IOException { writeJbiXmlModel( jbiInstance, targetFile.getLocation().toFile()); try { targetFile.refreshLocal( IResource.DEPTH_ZERO, new NullProgressMonitor()); } catch( CoreException e ) { PetalsCommonPlugin.log( e, IStatus.ERROR ); } } /** * Loads the JBI model instance from a jbi.xml file. * @param emfUri the EMF URI of the jbi.xml file * @return the JBI model * @throws InvalidJbiXmlException if the jbi.xml file is badly-formed */ public static Jbi getJbiXmlModel( org.eclipse.emf.common.util.URI emfUri ) throws InvalidJbiXmlException { try { ResourceSet resourceSet = new ResourceSetImpl(); Resource resource = resourceSet.getResource( emfUri, true ); resource.load( resourceSet.getLoadOptions()); DocumentRoot root = (DocumentRoot) resource.getContents().get( 0 ); return root.getJbi(); } catch( Exception e ) { throw new InvalidJbiXmlException( e ); } } /** * Loads the JBI model instance from a jbi.xml file. * @param jbiXmlFile the jbi.xml file * @return the JBI model * @throws InvalidJbiXmlException if the jbi.xml file is badly-formed */ public static Jbi getJbiXmlModel( File jbiXmlFile ) throws InvalidJbiXmlException { org.eclipse.emf.common.util.URI uri = org.eclipse.emf.common.util.URI.createFileURI( jbiXmlFile.getAbsolutePath()); return getJbiXmlModel( uri ); } /** * Validates an {@link EObject} with respect to the JBI meta-model. * @param jbiXmlElement the element to validate (generally the document root or the jbi element) * @return the validation diagnostic. * <p> * Its status should be {@link Diagnostic#OK} if no error was found. * </p> */ public static Diagnostic validateJbiXmlModel( EObject jbiXmlElement ) { return new JbiCustomDiagnostician().validate( jbiXmlElement ); } /** * Loads the jbi.xml file directly from the URL of a Petals archive. * @param petalsArchiveUri the URI of the Petals archive * @return the JBI instance * @throws InvalidJbiXmlException */ public static Jbi getJbiXmlModel( URI petalsArchiveUri ) throws InvalidJbiXmlException { org.eclipse.emf.common.util.URI emfUri = org.eclipse.emf.common.util.URI.createURI( "archive:" + petalsArchiveUri + "!/META-INF/jbi.xml" ); return JbiXmlUtils.getJbiXmlModel( emfUri ); } /** * Gets the WSDL element value. * @param provides the section whose WSDL must be retrieved * @return the WSDL element value (may be null) */ public static String getWsdlValue( Provides provides ) { for( int i=0; i<provides.getGroup().size(); i++ ) { FeatureMap.Entry f = provides.getGroup().get( i ); if( f == null ) continue; if( ! "wsdl".equalsIgnoreCase( f.getEStructuralFeature().getName())) continue; Object o = f.getValue(); if( o instanceof String ) return (String) o; if( !( o instanceof AnyType )) continue; FeatureMap featureMap = ((AnyType) o).getMixed(); for( int j=0; j<featureMap.size(); j++ ) { EStructuralFeature esf = featureMap.getEStructuralFeature( j ); if( FeatureMapUtil.isText( esf )) { String wsdlValue = featureMap.getValue( j ).toString().trim(); return wsdlValue; } } } return null; } /** * Gets the MEP element value. * @param consumes the section whose MEP must be retrieved * @return the MEP element value (may be null) */ public static String getMepValue( Consumes consumes ) { for( int i=0; i<consumes.getGroup().size(); i++ ) { FeatureMap.Entry f = consumes.getGroup().get( i ); if( f == null ) continue; if( ! "mep".equalsIgnoreCase( f.getEStructuralFeature().getName())) continue; Object o = f.getValue(); if( o instanceof String ) return (String) o; if( !( o instanceof AnyType )) continue; FeatureMap featureMap = ((AnyType)o).getMixed(); for( int j=0; j<featureMap.size(); j++ ) { EStructuralFeature esf = featureMap.getEStructuralFeature( j ); if( FeatureMapUtil.isText( esf )) { String mepValue = featureMap.getValue( j ).toString().trim(); return mepValue; } } } return null; } /** * Gets the jbi.xml file from a project. * @param project the SU project * @return the jbi.xml file * @throws FileNotFoundException if the jbi.xml file cannot be found */ public static IFile getJbiXmlFile( IProject project ) throws FileNotFoundException { IFile jbiXmlFile = project.getFile( PetalsConstants.LOC_JBI_FILE ); if( jbiXmlFile.exists()) return jbiXmlFile; throw new FileNotFoundException( "No jbi.xml file could be found in " + project.getName() + "." ); } /** * Gets the jbi.xml file from a project. * @param projectFile the SU project directory * @return the jbi.xml file * @throws FileNotFoundException if the jbi.xml file cannot be found */ public static File getJbiXmlFile( File projectFile ) throws FileNotFoundException { File jbiXmlFile = new File( projectFile, PetalsConstants.LOC_JBI_FILE ); if( jbiXmlFile.exists()) return jbiXmlFile; throw new FileNotFoundException( "No jbi.xml file could be found in " + projectFile.getAbsolutePath() + "." ); } /** * Gets the JBI model instance of a SU project. * @param project the project * @return the JBI model * @throws InvalidJbiXmlException if the jbi.xml file is badly-formed * @throws FileNotFoundException if the jbi.xml file does not exist */ public static Jbi getJbiXmlModel( IProject project ) throws InvalidJbiXmlException, FileNotFoundException { IFile jbiXmlFile = getJbiXmlFile( project ); return getJbiXmlModel( jbiXmlFile ); } /** * Loads the JBI model instance from a jbi.xml file. * @param jbiXmlFile the jbi.xml file * @return the JBI model * @throws InvalidJbiXmlException if the jbi.xml file is badly-formed */ public static Jbi getJbiXmlModel( IFile jbiXmlFile ) throws InvalidJbiXmlException { return getJbiXmlModel( jbiXmlFile.getLocation().toFile()); } /** * Gets the WSDL file from a provides section. * @param jbiXmlFile the jbi.xml file * @param provides the provides section * @return the WSDL file, or null if the WSDL element value is null or empty */ public static File getWsdlFile( IFile jbiXmlFile, Provides provides ) { String wsdlValue = getWsdlValue( provides ); return getWsdlFile( jbiXmlFile, wsdlValue ); } /** * Gets the WSDL file from a provides section. * @param jbiXmlFile the jbi.xml file * @param wsdlElementValue the WSDL element value * @return the WSDL file, or null if the WSDL element value is null or empty */ public static File getWsdlFile( IFile jbiXmlFile, String wsdlElementValue ) { File file = null; if( wsdlElementValue != null && wsdlElementValue.trim().length() != 0 ) { URI wsdlUri; try { wsdlUri = UriAndUrlHelper.urlToUri( wsdlElementValue ); } catch( Exception e ) { wsdlUri = null; } try { if( wsdlUri == null ) file = getResourceFile( jbiXmlFile.getProject(), wsdlElementValue ).getLocation().toFile(); else if( "file".equals( wsdlUri.getScheme())) file = new File( wsdlUri ); } catch( Exception e ) { // nothing } } return file; } /** * Gets the WSDL file from a provides section. * @param projectRoot a file pointing to the root of a SU project * @param wsdlElementValue the WSDL element value * @return the WSDL file, or null if the WSDL element value is null or empty */ public static File getWsdlFile( File projectRoot, String wsdlElementValue ) { File file = null; if( wsdlElementValue != null && wsdlElementValue.trim().length() != 0 ) { try { URI wsdlURI = UriAndUrlHelper.urlToUri( wsdlElementValue ); if( "file".equals( wsdlURI.getScheme())) file = new File( wsdlURI ); } catch( Exception e ) { PetalsCommonPlugin.log( e, IStatus.WARNING ); } try { if( file == null ) file = new File( new File( projectRoot, PetalsConstants.LOC_RES_FOLDER ), wsdlElementValue ); } catch( Exception e ) { PetalsCommonPlugin.log( e, IStatus.WARNING ); } } return file; } /** * It is not checked whether the returned resource file exists. * @param project * @param relativePath * @return * @throws FileNotFoundException */ public static IFile getResourceFile( IProject project, String relativePath ) throws FileNotFoundException { IFolder folder = project.getFolder( PetalsConstants.LOC_RES_FOLDER ); return folder.getFile( relativePath ); } /** * Indicates if a project contains provided services. * @param project a project (any project) * @return true if the project contains at least one provide, false otherwise */ public static boolean hasProvides( IProject project ) { boolean result = false; try { Jbi jbi = getJbiXmlModel( project ); if( jbi.getServices() != null ) { EList<Provides> provides = jbi.getServices().getProvides(); result = provides != null && provides.size() > 0; } } catch( InvalidJbiXmlException e ) { // nothing } catch( FileNotFoundException e ) { // nothing } return result; } /** * Checks whether a JBI descriptor describes a component. * @param jbiXmlFile the JBI descriptor to check * @return true if it describes a component, false otherwise */ public static boolean describesComponent( File jbiXmlFile ) { boolean result = false; try { Jbi jbi = getJbiXmlModel( jbiXmlFile ); result = jbi != null && jbi.getComponent() != null; } catch( InvalidJbiXmlException e ) { // nothing } return result; } /** * Checks whether a JBI descriptor describes a shared library. * @param jbiXmlFile the JBI descriptor to check * @return true if it describes a shared library, false otherwise */ public static boolean describesSharedLibrary( File jbiXmlFile ) { boolean result = false; try { Jbi jbi = getJbiXmlModel( jbiXmlFile ); result = jbi != null && jbi.getSharedLibrary() != null; } catch( InvalidJbiXmlException e ) { // nothing } return result; } /** * Checks whether a JBI descriptor describes a service unit. * @param jbiXmlFile the JBI descriptor to check * @return true if it describes a SU, false otherwise */ public static boolean describesServiceUnit( File jbiXmlFile ) { boolean result = false; try { Jbi jbi = getJbiXmlModel( jbiXmlFile ); result = jbi != null && jbi.getServices() != null; } catch( InvalidJbiXmlException e ) { // nothing } return result; } /** * Checks whether a JBI descriptor describes a service-assembly. * @param jbiXmlFile the JBI descriptor to check * @return true if it describes a SA, false otherwise */ public static boolean describesServiceAssembly( File jbiXmlFile ) { boolean result = false; try { Jbi jbi = getJbiXmlModel( jbiXmlFile ); result = jbi != null && jbi.getServiceAssembly() != null; } catch( InvalidJbiXmlException e ) { // nothing } return result; } }