package org.ebayopensource.turmeric.eclipse.buildsystem; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import javax.xml.namespace.QName; import org.ebayopensource.turmeric.common.config.LibraryType; import org.ebayopensource.turmeric.common.config.ReferredType; import org.ebayopensource.turmeric.common.config.TypeDependencyType; import org.ebayopensource.turmeric.common.config.TypeLibraryDependencyType; import org.ebayopensource.turmeric.eclipse.buildsystem.utils.BuildSystemUtil; import org.ebayopensource.turmeric.eclipse.core.TurmericCoreActivator; import org.ebayopensource.turmeric.eclipse.core.logging.SOALogger; import org.ebayopensource.turmeric.eclipse.core.resources.constants.SOAProjectConstants; import org.ebayopensource.turmeric.eclipse.repositorysystem.core.GlobalRepositorySystem; import org.ebayopensource.turmeric.eclipse.repositorysystem.core.ISOAProjectConfigurer; import org.ebayopensource.turmeric.eclipse.repositorysystem.core.SOAGlobalRegistryAdapter; import org.ebayopensource.turmeric.eclipse.resources.model.AssetInfo; import org.ebayopensource.turmeric.eclipse.resources.model.IAssetInfo; import org.ebayopensource.turmeric.eclipse.resources.util.SOAServiceUtil; import org.ebayopensource.turmeric.eclipse.typelibrary.TypeLibraryActivator; import org.ebayopensource.turmeric.eclipse.typelibrary.utils.TypeLibraryUtil; import org.ebayopensource.turmeric.eclipse.utils.collections.CollectionUtil; import org.ebayopensource.turmeric.eclipse.utils.plugin.ProgressUtil; import org.ebayopensource.turmeric.eclipse.utils.plugin.WorkspaceUtil; import org.ebayopensource.turmeric.tools.library.SOATypeRegistry; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; import org.eclipse.wst.wsdl.Definition; import org.eclipse.wst.wsdl.internal.util.WSDLResourceFactoryImpl; import org.eclipse.wst.wsdl.util.WSDLResourceImpl; import org.eclipse.xsd.XSDSchema; import org.eclipse.xsd.XSDSchemaDirective; import org.eclipse.xsd.XSDTypeDefinition; /** * The Class SynchronizeWsdlAndDepXML. */ public class SynchronizeWsdlAndDepXML { private Definition definition = null; private IProject project = null; /** * Instantiates a new synchronize wsdl and dep xml. * * @param project the project */ public SynchronizeWsdlAndDepXML(IProject project) { this.project = project; } /** * Wrapper method, Internally uses. * * @throws CoreException the core exception * @throws Exception the exception * @see {@link TypeLibSynhcronizer#syncronizeWSDLandDepXml(Definition, IProject)} */ public void syncronizeWsdlandDepXml() throws CoreException, Exception { final IFile wsdlFile = SOAServiceUtil.getWsdlFile(project.getName()); Job job = new Job("Synchronize WSDL and Dependent XML") { @Override protected IStatus run(IProgressMonitor monitor) { try { monitor.beginTask("Synchronize", IProgressMonitor.UNKNOWN); ResourceSet resourceSet = new ResourceSetImpl(); Resource.Factory.Registry registry = resourceSet .getResourceFactoryRegistry(); Map<String, Object> extensionToFactoryMap = registry .getExtensionToFactoryMap(); extensionToFactoryMap.put(SOAProjectConstants.WSDL, new WSDLResourceFactoryImpl()); URI uri = URI.createFileURI(wsdlFile.getLocation() .toString()); WSDLResourceImpl wsdlResource = (WSDLResourceImpl) resourceSet .createResource(uri); wsdlResource.load(null); definition = wsdlResource.getDefinition(); syncronizeWSDLandDepXml(definition); } catch (Exception e) { SOALogger.getLogger().error(e); monitor.done(); return Status.CANCEL_STATUS; } monitor.done(); return Status.OK_STATUS; } }; job.setUser(false); job.schedule(); } /** * Synchronize the xsd and the dependencies. Meaning, Scans the xsd, finds * the types that this type refers to and adds it to the dependencies if not * present. Also it removes the unwanted dependencies from the type * dependencies. Unwanted includes unwanted parent type references and types * referred from the parent type. * * @param schema the schema * @param type the type * @throws Exception the exception */ public void syncronizeXSDandDepXml(XSDSchema schema, QName type) throws Exception { IFile typeDepFile = TurmericCoreActivator.getDependencyFile(project); if (!typeDepFile.exists()) { TypeDepMarshaller.createDefaultDepXml(project, new NullProgressMonitor()); WorkspaceUtil.refresh(typeDepFile); } Map<LibraryType, XSDSchemaDirective> importedTypes = TypeLibraryActivator.getAllTypeLibImports(schema); TypeLibraryDependencyType typeLibraryDependencyType = TypeDepMarshaller .unmarshallIt(typeDepFile); // No imports for this type // so remove the entry if there is one if (importedTypes == null || importedTypes.size() == 0) { if (TypeDepMarshaller.removeTypeEntryIfExists( typeLibraryDependencyType, type.getLocalPart())) { TypeDepMarshaller.marshallIt(typeLibraryDependencyType, typeDepFile); return; } } else { Set<QName> xsdImportedTypes = new HashSet<QName>(); for (LibraryType libraryType : importedTypes.keySet()) { if (libraryType != null) xsdImportedTypes.add(TypeLibraryUtil.toQName(libraryType)); } boolean marshallReqd = false; SOAGlobalRegistryAdapter registryAdapter = SOAGlobalRegistryAdapter .getInstance(); SOATypeRegistry typeRegistry = registryAdapter.getGlobalRegistry(); LibraryType libraryType = typeRegistry.getType(type); // add Top level Type Entry if required marshallReqd = TypeDepMarshaller.addTypeEntryIfNotExists( typeLibraryDependencyType, libraryType); // check for version change for top level Type Entry if required marshallReqd = marshallReqd | TypeDepMarshaller.modifyTypeEntry( typeLibraryDependencyType, libraryType); TypeDependencyType typeDependencyType = TypeDepMarshaller .getTypeEntry(typeLibraryDependencyType, type.getLocalPart()); Set<QName> depXmlReferredTypes = TypeDepMarshaller .getAllReferredtypes(typeDependencyType); if (!CollectionUtil.twoWayDiff(xsdImportedTypes, depXmlReferredTypes).isEmpty()) { // this means there is a diff. // so there should be an IO. // To be safe lets remove everything from the dep xml and add // the reqd ones. // we believe CPUS are much fsater than hard disk heads :)) marshallReqd = true; // remove evrything first Set<ReferredType> oldReferredTpes = TypeDepMarshaller .getALLReferredTypes(typeLibraryDependencyType); TypeDepMarshaller.removeAllReferredTypes(typeDependencyType); TypeDepMarshaller.addAllReferredTypes(typeDependencyType, importedTypes.keySet(), oldReferredTpes); } if (marshallReqd) { TypeDepMarshaller.marshallIt(typeLibraryDependencyType, typeDepFile); } } } /** * Syncronize all xs dsand dep xml. * * @throws CoreException the core exception * @throws Exception the exception */ public void syncronizeAllXSDsandDepXml() throws CoreException, Exception { syncronizeAllXSDsandDepXml(null); } /** * Wrapper method, Internally uses. * * @param xsdFiles the xsd files * @throws CoreException the core exception * @throws Exception the exception * @see {@link TypeLibSynhcronizer#syncronizeXSDandDepXml(XSDSchema, IProject, QName) */ public void syncronizeAllXSDsandDepXml(List<IFile> xsdFiles) throws CoreException, Exception { // there could be some deleted XSDs also IFile typeDepFile = TurmericCoreActivator.getDependencyFile(project); List<IFile> allXSDFiles = xsdFiles != null ? xsdFiles : TypeLibraryUtil .getAllXsdFiles(project, true); List<String> allXSDStr = new ArrayList<String>(); if (!typeDepFile.exists()) { TypeDepMarshaller.createDefaultDepXml(project, new NullProgressMonitor()); WorkspaceUtil.refresh(typeDepFile); } for (IFile file : allXSDFiles) { if (file.exists()) { allXSDStr.add(TypeLibraryUtil.getXsdTypeNameFromFileName(file .getName())); } } boolean marshallIt = false; TypeLibraryDependencyType typeLibraryDependencyType = TypeDepMarshaller .unmarshallIt(typeDepFile); Iterator<TypeDependencyType> iterator = typeLibraryDependencyType .getType().iterator(); while (iterator.hasNext()) { TypeDependencyType typeDependencyType = iterator.next(); if (!allXSDStr.contains(typeDependencyType.getName())) { iterator.remove(); marshallIt = true; } } if (marshallIt) { TypeDepMarshaller .marshallIt(typeLibraryDependencyType, typeDepFile); } for (IFile file : allXSDFiles) { if (file.isAccessible()) { XSDSchema xsdSchema = TypeLibraryUtil.parseSchema(file .getLocation().toFile().toURI().toURL()); syncronizeXSDandDepXml(xsdSchema, TypeLibraryUtil.toQName(file)); } } } /** * Synchronize the wsdl and the dependencies. Meaning, Scans the wsdl, finds * the types and adds it to the dependencies if not present. Also it removes * the unwanted dependencies from the type dependencies. * * @param definition the definition * @throws Exception the exception */ public void syncronizeWSDLandDepXml(Definition definition) throws Exception { Map<LibraryType, XSDTypeDefinition> wsdlImportedSchemas = TypeLibraryActivator.getTypeLibraryTypes(definition); IFile typeDepFile = TurmericCoreActivator.getDependencyFile(project); if (!typeDepFile.exists()) { TypeDepMarshaller.createDefaultDepXml(project, new NullProgressMonitor()); WorkspaceUtil.refresh(typeDepFile); } TypeLibraryDependencyType typeLibraryDependencyType = TypeDepMarshaller .unmarshallIt(typeDepFile); String wsdlTypeName = GlobalRepositorySystem.instanceOf() .getActiveRepositorySystem().getTypeRegistryBridge() .getTypeDependencyWsdlTypeName(); if (wsdlImportedSchemas == null || wsdlImportedSchemas.size() == 0) { if (TypeDepMarshaller.removeTypeEntryIfExists( typeLibraryDependencyType, wsdlTypeName)) { TypeDepMarshaller.marshallIt(typeLibraryDependencyType, typeDepFile); return; } } else { boolean marshallReqd = false; LibraryType libraryType = TypeLibraryUtil .createLibraryType(wsdlTypeName); marshallReqd = TypeDepMarshaller.addTypeEntryIfNotExists( typeLibraryDependencyType, libraryType); TypeDependencyType typeDependencyType = TypeDepMarshaller .getTypeEntry(typeLibraryDependencyType, wsdlTypeName); Set<QName> depXmlReferredTypes = TypeDepMarshaller .getAllReferredtypes(typeDependencyType); Set<QName> wsdlImportedTypes = new HashSet<QName>(); for (LibraryType refLibraryType : wsdlImportedSchemas.keySet()) { wsdlImportedTypes.add(TypeLibraryUtil.toQName(refLibraryType)); } if (!CollectionUtil.twoWayDiff(wsdlImportedTypes, depXmlReferredTypes).isEmpty()) { // this means there is a diff. // so there should be an IO. // To be safe lets remove everything from the dep xml and add // the reqd ones. // we believe CPUS are much fsater than hard disk heads :)) marshallReqd = true; // remove evrything first Set<ReferredType> oldReferredTpes = TypeDepMarshaller .getALLReferredTypes(typeLibraryDependencyType); TypeDepMarshaller.removeAllReferredTypes(typeDependencyType); TypeDepMarshaller.addAllReferredTypes(typeDependencyType, wsdlImportedSchemas.keySet(), oldReferredTpes); } if (marshallReqd) { TypeDepMarshaller.marshallIt(typeLibraryDependencyType, typeDepFile); WorkspaceUtil.refresh(typeDepFile); } } } /** * Compare the type dependency and project dependency and synchronizes the * project dependencies to match the type dependency. One possible * optimization is to avoid removing and adding existing dependencies. Need * some enhancement from Bnr API also * * @param monitor the monitor * @throws Exception the exception */ public void synchronizeTypeDepandProjectDep(IProgressMonitor monitor) throws Exception { monitor = ProgressUtil.getDefaultMonitor(monitor); IFile typeDepFile = TurmericCoreActivator.getDependencyFile(project); Set<String> allXmlDepLibs = null; ProgressUtil.progressOneStep(monitor, 10); if (typeDepFile.exists()) { TypeLibraryDependencyType typeLibraryDependencyType = TypeDepMarshaller .unmarshallIt(typeDepFile); allXmlDepLibs = TypeDepMarshaller .getAllReferredTypeLibraries(typeLibraryDependencyType); allXmlDepLibs.addAll(GlobalRepositorySystem.instanceOf() .getActiveRepositorySystem().getTypeRegistryBridge() .getRequiredLibrariesForTypeLibraryProject()); // Add all other dependent libraries this type is referring to ProgressUtil.progressOneStep(monitor); SOAGlobalRegistryAdapter registryAdapter = SOAGlobalRegistryAdapter.getInstance(); SOATypeRegistry typeRegistry = registryAdapter.getGlobalRegistry(); for (QName qName : TypeDepMarshaller .getAllReferredTypes(typeLibraryDependencyType)) { for (String lib : typeRegistry.getLibrariesReferredByType(qName)) { allXmlDepLibs.add(lib); } } ProgressUtil.progressOneStep(monitor); // there could be the case that an xsd form this project is being // imported. // in that case no dep should go to project.xml. because both xsds // are in the same project if (allXmlDepLibs.contains(project.getName())) { allXmlDepLibs.remove(project.getName()); } List<AssetInfo> dependencies = GlobalRepositorySystem.instanceOf() .getActiveRepositorySystem().getAssetRegistry() .getDependencies(project.getName()); ProgressUtil.progressOneStep(monitor); Set<String> projTypeLibDeps = new HashSet<String>(); for (AssetInfo assetInfo : dependencies) { // We should add/remove only type libraries, don't play around // with any other dependency if (typeRegistry.getTypeLibrary(assetInfo.getName()) != null || allXmlDepLibs.contains(assetInfo.getName())) { //we also accept the required dependencies for TL which are //not necessarily a type library. projTypeLibDeps.add(assetInfo.getName()); } else if (allXmlDepLibs.contains(assetInfo.getShortDescription())) { projTypeLibDeps.add(assetInfo.getShortDescription()); } else if (allXmlDepLibs.contains(assetInfo.getDescription())) { projTypeLibDeps.add(assetInfo.getDescription()); } } if (!CollectionUtil.twoWayDiff(projTypeLibDeps, allXmlDepLibs) .isEmpty()) { // But here we don't think CPU is better than hard disk :)).. // Here there is a lot of change hitting the framework. so just // doing the necessary stuff Set<String> addedLibraries = CollectionUtil.oneWayDiff( allXmlDepLibs, projTypeLibDeps); Set<String> removedLibraries = CollectionUtil.oneWayDiff( projTypeLibDeps, allXmlDepLibs); ISOAProjectConfigurer projectConfigurer = GlobalRepositorySystem .instanceOf().getActiveRepositorySystem() .getProjectConfigurer(); String projectName = project.getName(); for (String addedLibrary : addedLibraries) { projectConfigurer.addTypeLibraryDependency(projectName, addedLibrary, IAssetInfo.TYPE_LIBRARY, true, monitor); } for (String removedLibrary : removedLibraries) { projectConfigurer.addTypeLibraryDependency(projectName, removedLibrary, IAssetInfo.TYPE_LIBRARY, false, monitor); } BuildSystemUtil.updateSOAClasspathContainer(project); } } } }