/* * JBoss, Home of Professional Open Source * Copyright 2005, JBoss Inc., and individual contributors as indicated * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.hibernate.console; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.OutputKeys; import javax.xml.transform.Result; import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.TransformerFactoryConfigurationError; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.eclipse.ui.console.ConsolePlugin; import org.eclipse.ui.console.IConsole; import org.eclipse.ui.console.IConsoleManager; import org.eclipse.ui.console.MessageConsole; import org.eclipse.ui.console.MessageConsoleStream; import org.hibernate.console.node.BaseNode; import org.hibernate.console.node.ConfigurationListNode; import org.jboss.tools.hibernate.runtime.spi.ISessionFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; /** * This class keeps track of the Hibernate Configurations that are known to * the Hibernate Console plugin. */ public class KnownConfigurations { // TODO: is the best way for the querypage model ? private QueryPageModel queryPages = new QueryPageModel(); private List<KnownConfigurationsListener> configurationListeners = new ArrayList<KnownConfigurationsListener>(); private Map<String, ConsoleConfiguration> configurations; private ConsoleConfigurationListener sfListener = new ConcoleConfigurationAdapter() { public void sessionFactoryClosing(final ConsoleConfiguration configuration, final ISessionFactory closingFactory) { fireNotification(new Notification() { public void notify(KnownConfigurationsListener listener) { listener.sessionFactoryClosing(configuration, closingFactory); } }); } public void sessionFactoryBuilt(final ConsoleConfiguration ccfg, final ISessionFactory builtSessionFactory) { fireNotification(new Notification() { public void notify(KnownConfigurationsListener listener) { listener.sessionFactoryBuilt(ccfg, builtSessionFactory); } }); } public void queryPageCreated(QueryPage qp) { queryPages.add(qp); } public void configurationBuilt(final ConsoleConfiguration ccfg) { fireNotification(new Notification() { public void notify(KnownConfigurationsListener listener) { listener.configurationBuilt(ccfg); } }); } public void configurationReset(final ConsoleConfiguration ccfg) { fireNotification(new Notification() { public void notify(KnownConfigurationsListener listener) { listener.configurationReset(ccfg); } }); }; }; private static KnownConfigurations instance; public static synchronized KnownConfigurations getInstance() { if (instance == null) { instance = new KnownConfigurations(); } return instance; } private abstract class Notification { public void run(KnownConfigurationsListener listener) { notify(listener); } /** * Subsclasses overide this method to send an event safely to a lsistener * @param listener */ protected abstract void notify(KnownConfigurationsListener listener); } /** * Register to receive notification of repository creation and disposal */ public void addConsoleConfigurationListener(KnownConfigurationsListener listener) { synchronized(configurationListeners) { configurationListeners.add(listener); } } /** * De-register a listener */ public void removeConfigurationListener(KnownConfigurationsListener listener) { synchronized(configurationListeners) { configurationListeners.remove(listener); } } /** * Add the repository to the receiver's list of known configurations. Doing this will enable * */ public ConsoleConfiguration addConfiguration(final ConsoleConfiguration configuration, boolean broadcast) { // Check the cache for an equivalent instance and if there is one, just update the cache ConsoleConfiguration existingConfiguration = internalGetRepository(configuration.getName() ); if (existingConfiguration == null) { // Store the location // Cache the location instance for later retrieval getRepositoriesMap().put(configuration.getName(), configuration); configuration.addConsoleConfigurationListener(sfListener); existingConfiguration = configuration; } if (broadcast) { fireNotification(new Notification() { public void notify(KnownConfigurationsListener listener) { listener.configurationAdded(configuration); } }); } return existingConfiguration; } public void removeAllConfigurations() { ConsoleConfiguration[] cfgs = getConfigurations(); for (int i = 0; i < cfgs.length; i++) { ConsoleConfiguration configuration = cfgs[i]; removeConfiguration(configuration, false); } } // added forUpdate as a workaround for letting listeners know it is done to update the configuration so they don't cause removal issues. public void removeConfiguration(final ConsoleConfiguration configuration, final boolean forUpdate) { ConsoleConfiguration oldConfig = getRepositoriesMap().remove(configuration.getName() ); if (oldConfig != null) { oldConfig.removeConsoleConfigurationListener(sfListener); fireNotification(new Notification() { public void notify(KnownConfigurationsListener listener) { listener.configurationRemoved(configuration, forUpdate); } }); oldConfig.reset(); removeLoggingStream( oldConfig ); } } /** * Answer whether the provided configuration name is known by the provider or not. * The name string corresponds to the String returned by ConsoleConfiguration#getName() */ public boolean isKnownConfiguration(String name) { return internalGetRepository(name) != null; } /** * Return a list of the know repository locations */ public ConsoleConfiguration[] getConfigurations() { return getRepositoriesMap().values().toArray(new ConsoleConfiguration[getRepositoriesMap().size()]); } public ConsoleConfiguration[] getConfigurationsSortedByName() { return getConfigurations(new Comparator<ConsoleConfiguration>() { public int compare(ConsoleConfiguration o1, ConsoleConfiguration o2) { return o1.getName().compareToIgnoreCase(o2.getName()); } }); } public ConsoleConfiguration[] getConfigurations(Comparator<ConsoleConfiguration> c) { ConsoleConfiguration[] configurations = getConfigurations(); Arrays.sort(configurations, c); return configurations; } private ConsoleConfiguration internalGetRepository(String location) { return getRepositoriesMap().get(location); } private Map<String, ConsoleConfiguration> getRepositoriesMap() { if (configurations == null) { configurations = new TreeMap<String, ConsoleConfiguration>(); } return configurations; } private KnownConfigurationsListener[] getListeners() { synchronized(configurationListeners) { return configurationListeners.toArray(new KnownConfigurationsListener[configurationListeners.size()]); } } private void fireNotification(Notification notification) { // Get a snapshot of the listeners so the list doesn't change while we're firing KnownConfigurationsListener[] listeners = getListeners(); // Notify each listener in a safe manner (i.e. so their exceptions don't kill us) for (int i = 0; i < listeners.length; i++) { KnownConfigurationsListener listener = listeners[i]; notification.run(listener); } } BaseNode rootNode = new ConfigurationListNode(this); public BaseNode getRootNode() { return rootNode; } // TODO: decouple this logging from Eclipse platform! private Map<String, Object[]> loggingStreams = new HashMap<String, Object[]>(); public MessageConsoleStream findLoggingStream(String name) { Object[] console = loggingStreams.get(name); if(console==null) { console = new Object[2]; String secondaryId = ConsoleMessages.KnownConfigurations_hibernate_log + (name==null?ConsoleMessages.KnownConfigurations_unknown:name); console[0] = new MessageConsole(secondaryId, null); IConsoleManager consoleManager = ConsolePlugin.getDefault().getConsoleManager(); consoleManager.addConsoles(new IConsole[] { (IConsole) console[0] }); console[1] = ((MessageConsole)console[0]).newMessageStream(); loggingStreams.put(name, console); } return (MessageConsoleStream) console[1]; } private void removeLoggingStream(ConsoleConfiguration oldConfig) { Object[] object = loggingStreams.remove( oldConfig.getName() ); if(object!=null) { MessageConsole mc = (MessageConsole)object[0]; MessageConsoleStream stream = (MessageConsoleStream)object[1]; try { stream.close(); } catch(IOException ie) { /* ignore */ }; IConsoleManager consoleManager = ConsolePlugin.getDefault().getConsoleManager(); consoleManager.removeConsoles( new IConsole[] { mc } ); } } public ConsoleConfiguration find(String lastUsedName) { if(configurations==null) return null; if(lastUsedName==null) return null; return configurations.get(lastUsedName); } public QueryPageModel getQueryPageModel() { return queryPages; } public void writeStateTo(File f) { try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.newDocument(); Element element = document.createElement("hibernate-console"); //$NON-NLS-1$ document.appendChild(element); ConsoleConfiguration[] configs = getConfigurations(); for (int i = 0; i < configs.length; i++) { ConsoleConfiguration cfg = configs[i]; cfg.getPreferences().writeStateTo(element); } writeXml(document, f); } catch (TransformerConfigurationException e) { throw new HibernateConsoleRuntimeException(ConsoleMessages.KnownConfigurations_could_not_write_state,e); } catch (TransformerException e) { throw new HibernateConsoleRuntimeException(ConsoleMessages.KnownConfigurations_could_not_write_state,e); } catch (ParserConfigurationException e) { throw new HibernateConsoleRuntimeException(ConsoleMessages.KnownConfigurations_could_not_write_state,e); } } private void writeXml(Document document, File f) throws TransformerConfigurationException, TransformerFactoryConfigurationError, TransformerException { // Prepare the DOM document for writing Source source = new DOMSource(document); // Prepare the output file Result result = new StreamResult(f); // Write the DOM document to the file Transformer xformer = TransformerFactory.newInstance().newTransformer(); xformer.setOutputProperty(OutputKeys.INDENT, "true"); //$NON-NLS-1$ xformer.transform(source, result); } List<ConsoleQueryParameter> queryParameters = new ArrayList<ConsoleQueryParameter>(); public ConsoleQueryParameter[] getQueryParameters() { return queryParameters.toArray(new ConsoleQueryParameter[queryParameters.size()]); } public List<ConsoleQueryParameter> getQueryParameterList() { return queryParameters; } }