/******************************************************************************* * 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.repositorysystem.core; import java.io.File; 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.SOATypeLibraryConstants; import org.ebayopensource.turmeric.eclipse.resources.model.AssetInfo; import org.ebayopensource.turmeric.eclipse.soatools.Activator; import org.ebayopensource.turmeric.eclipse.utils.classloader.SOAPluginClassLoader; import org.ebayopensource.turmeric.eclipse.utils.collections.ListUtil; 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.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.osgi.framework.Bundle; /** * The Class SOAGlobalRegistryAdapter. * * @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 single instance of SOAGlobalRegistryAdapter */ public static SOAGlobalRegistryAdapter getInstance() { return registryAdapter; } /** * Gets the global registry. * * @return the global registry * @throws Exception the exception */ public SOATypeRegistry getGlobalRegistry() throws Exception { if (soaTypeRegistry == null) { long startTime = System.currentTimeMillis(); synchronized (SOAGlobalRegistryAdapter.class) { if (soaTypeRegistry == null) { Job job = new GlobalRegistryJob("Retrieve Global Registry"); job.setUser(false); job.schedule(); 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); // } int cnt = 0; // while ((job.getState() == Job.RUNNING || job.getState() == Job.WAITING)) { while (cnt < 5 && soaTypeRegistry == null) { logger.warning("SOA types registry not initialized yet, sleeping..."); Thread.sleep(1000); cnt++; } } 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 the typelib names * @throws Exception the 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 Exception the exception */ 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(); } /** * Refresh type dependency in soa type registry. * * @param typeLibraryName the type library name * @throws CoreException the core exception * @throws Exception the exception */ 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()); } // adding type lib projects in workspace for (IProject project : WorkspaceUtil.getAllProjectsInWorkSpace()) { if (project.isAccessible() && project.hasNature("org.ebayopensource.turmeric.eclipse.typelibrary.TypeLibraryProjectNature")) { 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])); } /** * Adds the type to registry. * * @param libraryType the library type * @throws Exception the exception */ 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); } } private class GlobalRegistryJob extends Job { public GlobalRegistryJob(String name) { super(name); } @Override protected IStatus run(IProgressMonitor monitor) { monitor.beginTask( "Initializing SOA Type Registry...", 100); monitor.internalWorked(10); final ClassLoader originalClassLoader = Thread .currentThread().getContextClassLoader(); try { init(); monitor.worked(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.worked(40); typeLibclassLoader.setPluginBundles( (GlobalRepositorySystem .instanceOf().getActiveRepositorySystem() .getTypeRegistryBridge().getPluginBundles())); monitor.worked(10); Thread.currentThread().setContextClassLoader( typeLibclassLoader); monitor.worked(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.worked(10); soaTypeRegistry = typeReg; } catch (Exception e) { logger.error(e); monitor.done(); return Status.CANCEL_STATUS; } finally { Thread.currentThread().setContextClassLoader( originalClassLoader); monitor.done(); } return Status.OK_STATUS; } } }