/******************************************************************************* * Copyright (c) 2006-2010 eBay Inc. All Rights Reserved. * Licensed 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 *******************************************************************************/ package org.ebayopensource.turmeric.eclipse.ui.monitor.typelib; import java.io.File; import java.lang.reflect.InvocationTargetException; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import org.ebayopensource.turmeric.common.config.LibraryType; import org.ebayopensource.turmeric.eclipse.core.logging.SOALogger; import org.ebayopensource.turmeric.eclipse.core.resources.constants.SOAProjectConstants.SupportedProjectType; import org.ebayopensource.turmeric.eclipse.exception.resources.SOAInvocationException; import org.ebayopensource.turmeric.eclipse.repositorysystem.core.GlobalRepositorySystem; import org.ebayopensource.turmeric.eclipse.repositorysystem.core.ITypeRegistryBridge; import org.ebayopensource.turmeric.eclipse.resources.model.AssetInfo; import org.ebayopensource.turmeric.eclipse.soatools.Activator; import org.ebayopensource.turmeric.eclipse.ui.views.registry.SOATypeLibraryConstants; import org.ebayopensource.turmeric.eclipse.utils.classloader.SOAPluginClassLoader; import org.ebayopensource.turmeric.eclipse.utils.collections.ListUtil; import org.ebayopensource.turmeric.eclipse.utils.plugin.ProgressUtil; import org.ebayopensource.turmeric.eclipse.utils.plugin.WorkspaceUtil; import org.ebayopensource.turmeric.tools.library.RegistryUpdateDetails; import org.ebayopensource.turmeric.tools.library.SOAGlobalRegistryFactory; import org.ebayopensource.turmeric.tools.library.SOATypeRegistry; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.progress.IProgressService; import org.osgi.framework.Bundle; /** * @author smathew * * This class adapts the SOA Registry from Tools to Plugin. * * The changes to SOA Tools API should only affect this class. * */ public class SOAGlobalRegistryAdapter { private static SOATypeRegistry soaTypeRegistry = null; private static Set<String> typeLibNamesForSOATools; private static Set<File> typeLibLocationsForSOATools; private static SOAPluginClassLoader typeLibclassLoader; private static final SOALogger logger = SOALogger.getLogger(); private static final SOAGlobalRegistryAdapter registryAdapter = new SOAGlobalRegistryAdapter(); private SOAGlobalRegistryAdapter() { } /** * Returns the global singleton instance representing a type registry. A * progress monitor would be displayed if called from a UI thread Otherwise * this willbe a silent operation * * @return * @throws Exception */ public static SOAGlobalRegistryAdapter getInstance() { return registryAdapter; } public SOATypeRegistry getGlobalRegistry() throws Exception { if (soaTypeRegistry == null) { long startTime = System.currentTimeMillis(); synchronized (SOAGlobalRegistryAdapter.class) { if (soaTypeRegistry == null) { // we should use a separate thread if this is not being // called from a UI thread. final IRunnableWithProgress runnable = new IRunnableWithProgress() { public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { monitor.beginTask( "Initializing SOA Type Registry...", 100); monitor.internalWorked(10); final ClassLoader originalClassLoader = Thread .currentThread().getContextClassLoader(); try { init(); monitor.internalWorked(20); Thread thread = Thread.currentThread(); ClassLoader loader = thread.getContextClassLoader(); thread.setContextClassLoader(SOAGlobalRegistryFactory.class.getClassLoader()); SOATypeRegistry typeReg = GlobalRepositorySystem .instanceOf().getActiveRepositorySystem() .getTypeRegistryBridge().getSOATypeRegistry(); thread.setContextClassLoader(loader); monitor.internalWorked(40); typeLibclassLoader.setPluginBundles( (GlobalRepositorySystem .instanceOf().getActiveRepositorySystem() .getTypeRegistryBridge().getPluginBundles())); monitor.internalWorked(10); Thread.currentThread().setContextClassLoader( typeLibclassLoader); monitor.internalWorked(10); List<RegistryUpdateDetails> libraries = typeReg.populateRegistryWithTypeLibrariesDetailed(ListUtil.arrayList( typeLibNamesForSOATools)); if (libraries != null) { for (RegistryUpdateDetails details : libraries) { if (details.isUpdateSucess() == false) { logger.warning("Invalid type library->", details.getLibraryName(), ". Detailed Error: ", details.getMessage()); } } } monitor.internalWorked(10); soaTypeRegistry = typeReg; } catch (Exception e) { throw new SOAInvocationException(e); } finally { Thread.currentThread().setContextClassLoader( originalClassLoader); monitor.done(); } } }; try { if (Display.getCurrent() == null) { // non-UI thread runnable.run(ProgressUtil.getDefaultMonitor(null)); } else { final IProgressService service = PlatformUI .getWorkbench().getProgressService(); service.run(false, false, runnable); } while (soaTypeRegistry == null) { logger.warning("SOA types registry not initialized yet, sleeping..."); Thread.sleep(1000); } } finally { if (SOALogger.DEBUG) { long duration = System.currentTimeMillis() - startTime; logger.info("Time taken for initializing SOA global type registry is ", duration, " ms."); } } } } } return soaTypeRegistry; } /** * Codegen requires the type library names to create the registry object. * This API takes the typeLibrary names, find the location out, build a * class loader and pass the type lib names to codegen to populate the * registry. * * @param typelibNames * @throws Exception */ public void populateRegistry(String... typelibNames) throws Exception { getGlobalRegistry(); ClassLoader originalClassLoader = Thread.currentThread() .getContextClassLoader(); try { init(); ArrayList<Bundle> bundles = new ArrayList<Bundle>(); bundles.add(Activator.getDefault().getBundle()); typeLibclassLoader.setPluginBundles(bundles); if (SOALogger.DEBUG) { logger.debug("In populate Registry URLs are:", typeLibclassLoader.getM_classPathURLs()); } Thread.currentThread().setContextClassLoader(typeLibclassLoader); final List<RegistryUpdateDetails> libraries = soaTypeRegistry.populateRegistryWithTypeLibrariesDetailed(ListUtil.arrayList( typelibNames)); if (libraries != null) { for (RegistryUpdateDetails details : libraries) { if (details.isUpdateSucess() == false) { logger.warning("Invalid type library->", details.getLibraryName(), ". Detailed Error: ", details.getMessage()); } } } } finally { Thread.currentThread().setContextClassLoader(originalClassLoader); } } /** * To make sure that we give user an option to refresh his registry. reason * being there is no extension point in the ebay Build plugin now. Its under * development */ public void invalidateRegistry() { soaTypeRegistry = null; } /** * Sets up the classpath based on the repo system jar info and lib info * * @throws MalformedURLException */ public void init() throws Exception { typeLibNamesForSOATools = new HashSet<String>(); typeLibLocationsForSOATools = new HashSet<File>(); // adding the jars ITypeRegistryBridge typeRegistryBridge = GlobalRepositorySystem .instanceOf().getActiveRepositorySystem() .getTypeRegistryBridge(); final List<AssetInfo> typeLibs = typeRegistryBridge.getAllLatestTypeLibraries(); if (typeLibs != null) { for (AssetInfo assetInfo : typeLibs) { // Filtering the jars if we have a project here in workspace if (!WorkspaceUtil.getProject(assetInfo.getName()) .isAccessible()) { // add the typlib Name String typeLibNamesForSOATools.add(assetInfo.getName()); // add the jar files Set<File> fileSet = assetInfo.getFiles(true); typeLibLocationsForSOATools.addAll(fileSet); } } } populateClassLoader(); } public void refreshTypeDependencyInSOATypeRegistry(String typeLibraryName) throws CoreException, Exception{ populateClassLoader(); ClassLoader current = Thread.currentThread().getContextClassLoader(); try{ Thread.currentThread().setContextClassLoader(typeLibclassLoader); GlobalRepositorySystem.instanceOf().getActiveRepositorySystem().getTypeRegistryBridge() .processTypeDepXMLFile(typeLibraryName); }finally{ Thread.currentThread().setContextClassLoader(current); } } private void populateClassLoader() throws CoreException, Exception { Set<URL> urlsSet = new HashSet<URL>(); for (File file : typeLibLocationsForSOATools) { urlsSet.add(file.toURI().toURL()); } String typeLibNatureID = GlobalRepositorySystem.instanceOf() .getActiveRepositorySystem() .getProjectNatureId(SupportedProjectType.TYPE_LIBRARY); // adding type lib projects in workspace for (IProject project : WorkspaceUtil.getAllProjectsInWorkSpace()) { if (project.isAccessible() && project.hasNature(typeLibNatureID)) { urlsSet.add(project .getFolder(SOATypeLibraryConstants.FOLDER_GEN_META_SRC) .getLocation().toFile().toURI().toURL()); urlsSet.add(project .getFolder(SOATypeLibraryConstants.FOLDER_META_SRC) .getLocation().toFile().toURI().toURL()); typeLibNamesForSOATools.add(project.getName()); } } if (SOALogger.DEBUG) { for (URL url : urlsSet) { logger.debug("populate classloader" + url); } } typeLibclassLoader = new SOAPluginClassLoader("SOATools", urlsSet .toArray(new URL[0])); } public void addTypeToRegistry(LibraryType libraryType) throws Exception { populateClassLoader(); ClassLoader current = Thread.currentThread().getContextClassLoader(); try{ Thread.currentThread().setContextClassLoader(typeLibclassLoader); GlobalRepositorySystem.instanceOf().getActiveRepositorySystem().getTypeRegistryBridge() .getSOATypeRegistry().addTypeToRegistry(libraryType); }finally{ Thread.currentThread().setContextClassLoader(current); } } }