/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.directory.studio.ldapbrowser.core; import java.beans.Encoder; import java.beans.Expression; import java.beans.PersistenceDelegate; import java.beans.XMLDecoder; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.HashMap; import java.util.Map; import org.apache.directory.api.util.FileUtils; import org.apache.directory.studio.connection.core.Connection; import org.apache.directory.studio.connection.core.ConnectionCorePlugin; import org.apache.directory.studio.connection.core.ConnectionFolder; import org.apache.directory.studio.connection.core.Utils; import org.apache.directory.studio.connection.core.event.ConnectionEventRegistry; import org.apache.directory.studio.connection.core.event.ConnectionUpdateListener; import org.apache.directory.studio.connection.core.io.ConnectionIOException; import org.apache.directory.studio.ldapbrowser.core.events.BookmarkUpdateEvent; import org.apache.directory.studio.ldapbrowser.core.events.BookmarkUpdateListener; import org.apache.directory.studio.ldapbrowser.core.events.BrowserConnectionUpdateEvent; import org.apache.directory.studio.ldapbrowser.core.events.BrowserConnectionUpdateListener; import org.apache.directory.studio.ldapbrowser.core.events.EventRegistry; import org.apache.directory.studio.ldapbrowser.core.events.SearchUpdateEvent; import org.apache.directory.studio.ldapbrowser.core.events.SearchUpdateListener; import org.apache.directory.studio.ldapbrowser.core.model.BookmarkParameter; import org.apache.directory.studio.ldapbrowser.core.model.IBookmark; import org.apache.directory.studio.ldapbrowser.core.model.IBrowserConnection; import org.apache.directory.studio.ldapbrowser.core.model.ISearch; import org.apache.directory.studio.ldapbrowser.core.model.SearchParameter; import org.apache.directory.studio.ldapbrowser.core.model.impl.Bookmark; import org.apache.directory.studio.ldapbrowser.core.model.impl.BrowserConnection; import org.apache.directory.studio.ldapbrowser.core.model.impl.Search; import org.apache.directory.studio.ldapbrowser.core.model.schema.Schema; /** * This class is used to manage {@link IBrowserConnection}s. * * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> */ public class BrowserConnectionManager implements ConnectionUpdateListener, BrowserConnectionUpdateListener, SearchUpdateListener, BookmarkUpdateListener { /** The list of connections. */ private Map<String, IBrowserConnection> connectionMap; /** * Creates a new instance of ConnectionManager. */ public BrowserConnectionManager() { this.connectionMap = new HashMap<String, IBrowserConnection>(); // no need to fire events while loading connections EventRegistry.suspendEventFiringInCurrentThread(); loadBrowserConnections(); EventRegistry.resumeEventFiringInCurrentThread(); ConnectionEventRegistry.addConnectionUpdateListener( this, ConnectionCorePlugin.getDefault().getEventRunner() ); EventRegistry.addSearchUpdateListener( this, BrowserCorePlugin.getDefault().getEventRunner() ); EventRegistry.addBookmarkUpdateListener( this, BrowserCorePlugin.getDefault().getEventRunner() ); EventRegistry.addBrowserConnectionUpdateListener( this, BrowserCorePlugin.getDefault().getEventRunner() ); } /** * Gets the Schema Cache filename for the corresponding browser connection. * * @param browserConnection * the browser connection * @return * the Schema Cache filename for the corresponding browser connection */ public static final String getSchemaCacheFileName( String id ) { return BrowserCorePlugin.getDefault().getStateLocation().append( "schema-" + Utils.getFilenameString( id ) + ".ldif" ).toOSString(); //$NON-NLS-1$ //$NON-NLS-2$ } /** * Gets the filename of the Connection Store. * * @return * the filename of the Connection Store */ public static final String getBrowserConnectionStoreFileName() { String filename = BrowserCorePlugin.getDefault().getStateLocation() .append( "browserconnections.xml" ).toOSString(); //$NON-NLS-1$ File file = new File( filename ); if ( !file.exists() ) { // try to convert old connections.xml: // 1st search it in current workspace with the old ldapstudio plugin ID // 2nd search it in old .ldapstudio workspace with the old ldapstudio plugin ID String[] oldFilenames = new String[2]; oldFilenames[0] = filename.replace( "org.apache.directory.studio.ldapbrowser.core", //$NON-NLS-1$ "org.apache.directory.ldapstudio.browser.core" ); //$NON-NLS-1$ oldFilenames[1] = oldFilenames[0].replace( ".ApacheDirectoryStudio", ".ldapstudio" ); //$NON-NLS-1$ //$NON-NLS-2$ for ( int i = 0; i < oldFilenames.length; i++ ) { File oldFile = new File( oldFilenames[i] ); if ( oldFile.exists() ) { try { String oldContent = FileUtils.readFileToString( oldFile, "UTF-8" ); //$NON-NLS-1$ String newContent = oldContent.replace( "org.apache.directory.ldapstudio.browser.core", //$NON-NLS-1$ "org.apache.directory.studio.ldapbrowser.core" ); //$NON-NLS-1$ FileUtils.writeStringToFile( file, newContent, "UTF-8" ); //$NON-NLS-1$ break; } catch ( IOException e ) { e.printStackTrace(); } } } } return filename; } /** * Gets a browser connection from its id. * * @param id * the id of the Connection * @return * the corresponding IBrowserConnection */ public IBrowserConnection getBrowserConnectionById( String id ) { return connectionMap.get( id ); } /** * Gets a browser connection from its name. * * @param name * the name of the Connection * @return * the corresponding IBrowserConnection */ public IBrowserConnection getBrowserConnectionByName( String name ) { Connection connection = ConnectionCorePlugin.getDefault().getConnectionManager().getConnectionByName( name ); return getBrowserConnection( connection ); } /** * Gets a browser connection from its underlying connection. * * @param connection * the underlying connection * @return * the corresponding IBrowserConnection */ public IBrowserConnection getBrowserConnection( Connection connection ) { return connection != null ? getBrowserConnectionById( connection.getId() ) : null; } /** * Gets an array containing all the Connections. * * @return * an array containing all the Connections */ public IBrowserConnection[] getBrowserConnections() { return ( IBrowserConnection[] ) connectionMap.values().toArray( new IBrowserConnection[0] ); } /** * @see org.apache.directory.studio.connection.core.event.ConnectionUpdateListener#connectionRemoved(org.apache.directory.studio.connection.core.Connection) */ public void connectionRemoved( Connection connection ) { // update connection list connectionMap.remove( connection.getId() ); // remove schema file File schemaFile = new File( getSchemaCacheFileName( connection.getId() ) ); if ( schemaFile.exists() ) { schemaFile.delete(); } // make persistent saveBrowserConnections(); } /** * @see org.apache.directory.studio.connection.core.event.ConnectionUpdateListener#connectionAdded(org.apache.directory.studio.connection.core.Connection) */ public void connectionAdded( Connection connection ) { // update connection list BrowserConnection browserConnection = new BrowserConnection( connection ); connectionMap.put( connection.getId(), browserConnection ); // make persistent saveBrowserConnections(); } /** * @see org.apache.directory.studio.connection.core.event.ConnectionUpdateListener#connectionUpdated(org.apache.directory.studio.connection.core.Connection) */ public void connectionUpdated( Connection connection ) { saveBrowserConnections(); saveSchema( getBrowserConnection( connection ) ); } /** * @see org.apache.directory.studio.connection.core.event.ConnectionUpdateListener#connectionOpened(org.apache.directory.studio.connection.core.Connection) */ public void connectionOpened( Connection connection ) { } /** * @see org.apache.directory.studio.connection.core.event.ConnectionUpdateListener#connectionClosed(org.apache.directory.studio.connection.core.Connection) */ public void connectionClosed( Connection connection ) { } /** * @see org.apache.directory.studio.connection.core.event.ConnectionUpdateListener#connectionFolderModified(org.apache.directory.studio.connection.core.ConnectionFolder) */ public void connectionFolderModified( ConnectionFolder connectionFolder ) { } /** * @see org.apache.directory.studio.connection.core.event.ConnectionUpdateListener#connectionFolderAdded(org.apache.directory.studio.connection.core.ConnectionFolder) */ public void connectionFolderAdded( ConnectionFolder connectionFolder ) { } /** * @see org.apache.directory.studio.connection.core.event.ConnectionUpdateListener#connectionFolderRemoved(org.apache.directory.studio.connection.core.ConnectionFolder) */ public void connectionFolderRemoved( ConnectionFolder connectionFolder ) { } /** * @see org.apache.directory.studio.ldapbrowser.core.events.BrowserConnectionUpdateListener#browserConnectionUpdated(org.apache.directory.studio.ldapbrowser.core.events.BrowserConnectionUpdateEvent) */ public void browserConnectionUpdated( BrowserConnectionUpdateEvent browserConnectionUpdateEvent ) { if ( browserConnectionUpdateEvent.getDetail() == BrowserConnectionUpdateEvent.Detail.SCHEMA_UPDATED ) { saveSchema( browserConnectionUpdateEvent.getBrowserConnection() ); } } /** * {@inheritDoc} */ public void searchUpdated( SearchUpdateEvent searchUpdateEvent ) { if ( searchUpdateEvent.getDetail() == SearchUpdateEvent.EventDetail.SEARCH_ADDED || searchUpdateEvent.getDetail() == SearchUpdateEvent.EventDetail.SEARCH_REMOVED || searchUpdateEvent.getDetail() == SearchUpdateEvent.EventDetail.SEARCH_RENAMED || searchUpdateEvent.getDetail() == SearchUpdateEvent.EventDetail.SEARCH_PARAMETER_UPDATED ) { saveBrowserConnections(); } } /** * {@inheritDoc} */ public void bookmarkUpdated( BookmarkUpdateEvent bookmarkUpdateEvent ) { if ( bookmarkUpdateEvent.getDetail() == BookmarkUpdateEvent.Detail.BOOKMARK_ADDED || bookmarkUpdateEvent.getDetail() == BookmarkUpdateEvent.Detail.BOOKMARK_REMOVED || bookmarkUpdateEvent.getDetail() == BookmarkUpdateEvent.Detail.BOOKMARK_UPDATED ) { saveBrowserConnections(); } } /** * Saves the browser Connections */ private void saveBrowserConnections() { // To avoid a corrupt file, save object to a temp file first try { BrowserConnectionIO.save( new FileOutputStream( getBrowserConnectionStoreFileName() + "-temp" ), //$NON-NLS-1$ connectionMap ); } catch ( IOException e ) { // TODO Auto-generated catch block e.printStackTrace(); } // move temp file to good file File file = new File( getBrowserConnectionStoreFileName() ); File tempFile = new File( getBrowserConnectionStoreFileName() + "-temp" ); //$NON-NLS-1$ if ( file.exists() ) { file.delete(); } try { String content = FileUtils.readFileToString( tempFile, "UTF-8" ); //$NON-NLS-1$ FileUtils.writeStringToFile( file, content, "UTF-8" ); //$NON-NLS-1$ } catch ( IOException e ) { // TODO Auto-generated catch block e.printStackTrace(); } // Object[][] object = new Object[connectionMap.size()][3]; // // Iterator<IBrowserConnection> connectionIterator = connectionMap.values().iterator(); // for ( int i = 0; connectionIterator.hasNext(); i++ ) // { // IBrowserConnection browserConnection = connectionIterator.next(); // // ISearch[] searches = browserConnection.getSearchManager().getSearches(); // SearchParameter[] searchParameters = new SearchParameter[searches.length]; // for ( int k = 0; k < searches.length; k++ ) // { // searchParameters[k] = searches[k].getSearchParameter(); // } // // IBookmark[] bookmarks = browserConnection.getBookmarkManager().getBookmarks(); // BookmarkParameter[] bookmarkParameters = new BookmarkParameter[bookmarks.length]; // for ( int k = 0; k < bookmarks.length; k++ ) // { // bookmarkParameters[k] = bookmarks[k].getBookmarkParameter(); // } // // object[i][0] = browserConnection.getConnection().getId(); // object[i][1] = searchParameters; // object[i][2] = bookmarkParameters; // } // // save( object, getBrowserConnectionStoreFileName() ); } /** * Saves the Schema of the Connection * * @param browserConnection * the Connection */ private void saveSchema( IBrowserConnection browserConnection ) { if ( browserConnection == null ) { return; } try { String filename = getSchemaCacheFileName( browserConnection.getConnection().getId() ); FileWriter writer = new FileWriter( filename ); browserConnection.getSchema().saveToLdif( writer ); writer.close(); } catch ( Exception e ) { e.printStackTrace(); } } /** * Loads the Connections */ private void loadBrowserConnections() { Connection[] connections = ConnectionCorePlugin.getDefault().getConnectionManager().getConnections(); for ( int i = 0; i < connections.length; i++ ) { Connection connection = connections[i]; BrowserConnection browserConnection = new BrowserConnection( connection ); connectionMap.put( connection.getId(), browserConnection ); try { String schemaFilename = getSchemaCacheFileName( connection.getId() ); FileReader reader = new FileReader( schemaFilename ); Schema schema = new Schema(); schema.loadFromLdif( reader ); browserConnection.setSchema( schema ); } catch ( Exception e ) { } } // java.beans.XMLDecoder try { String fileName = getBrowserConnectionStoreFileName(); File file = new File( fileName ); if ( file.exists() ) { String oldContent = FileUtils.readFileToString( file, "UTF-8" ); //$NON-NLS-1$ if ( !oldContent.contains( "java.beans.XMLDecoder" ) ) //$NON-NLS-1$ { // new file format try { BrowserConnectionIO.load( new FileInputStream( getBrowserConnectionStoreFileName() ), connectionMap ); } catch ( Exception e ) { // If loading failed, try with temp file try { BrowserConnectionIO.load( new FileInputStream( getBrowserConnectionStoreFileName() + "-temp" ), connectionMap ); //$NON-NLS-1$ } catch ( FileNotFoundException e1 ) { // TODO Auto-generated catch block return; } catch ( ConnectionIOException e1 ) { // TODO Auto-generated catch block return; } } } else { // old file format Object[][] object = ( Object[][] ) this.load( getBrowserConnectionStoreFileName() ); if ( object != null ) { try { for ( int i = 0; i < object.length; i++ ) { String connectionId = ( String ) object[i][0]; IBrowserConnection browserConnection = getBrowserConnectionById( connectionId ); if ( browserConnection != null ) { if ( object[i].length > 0 ) { SearchParameter[] searchParameters = ( SearchParameter[] ) object[i][1]; for ( int k = 0; k < searchParameters.length; k++ ) { ISearch search = new Search( browserConnection, searchParameters[k] ); browserConnection.getSearchManager().addSearch( search ); } } if ( object[i].length > 1 ) { BookmarkParameter[] bookmarkParameters = ( BookmarkParameter[] ) object[i][2]; for ( int k = 0; k < bookmarkParameters.length; k++ ) { IBookmark bookmark = new Bookmark( browserConnection, bookmarkParameters[k] ); browserConnection.getBookmarkManager().addBookmark( bookmark ); } } } } } catch ( ArrayIndexOutOfBoundsException e ) { // Thrown by decoder.readObject(), signals EOF } catch ( Exception e ) { e.printStackTrace(); } } } } } catch ( Exception e ) { } } /** * Loads an Object from an XML file * * @param filename * the filename of the XML file * @return * the deserialized Object */ private synchronized Object load( String filename ) { try { Thread.currentThread().setContextClassLoader( getClass().getClassLoader() ); XMLDecoder decoder = new XMLDecoder( new BufferedInputStream( ( new FileInputStream( filename ) ) ) ); Object object = decoder.readObject(); decoder.close(); return object; } catch ( IOException ioe ) { return null; } catch ( Exception e ) { // if loading failed, try with temp file String tempFilename = filename + "-temp"; //$NON-NLS-1$ try { XMLDecoder decoder = new XMLDecoder( new BufferedInputStream( ( new FileInputStream( tempFilename ) ) ) ); Object object = decoder.readObject(); decoder.close(); return object; } catch ( IOException ioe2 ) { return null; } catch ( Exception e2 ) { return null; } } } class TypeSafeEnumPersistenceDelegate extends PersistenceDelegate { protected boolean mutatesTo( Object oldInstance, Object newInstance ) { return oldInstance == newInstance; } protected Expression instantiate( Object oldInstance, Encoder out ) { Class<?> type = oldInstance.getClass(); if ( !Modifier.isPublic( type.getModifiers() ) ) { throw new IllegalArgumentException( "Could not instantiate instance of non-public class: " //$NON-NLS-1$ + oldInstance ); } for ( Field field : type.getFields() ) { int mod = field.getModifiers(); if ( Modifier.isPublic( mod ) && Modifier.isStatic( mod ) && Modifier.isFinal( mod ) && ( type == field.getDeclaringClass() ) ) { try { if ( oldInstance == field.get( null ) ) { return new Expression( oldInstance, field, "get", new Object[] //$NON-NLS-1$ { null } ); } } catch ( IllegalAccessException exception ) { throw new IllegalArgumentException( "Could not get value of the field: " + field, exception ); //$NON-NLS-1$ } } } throw new IllegalArgumentException( "Could not instantiate value: " + oldInstance ); //$NON-NLS-1$ } } }