001    /*
002     *  Licensed to the Apache Software Foundation (ASF) under one
003     *  or more contributor license agreements.  See the NOTICE file
004     *  distributed with this work for additional information
005     *  regarding copyright ownership.  The ASF licenses this file
006     *  to you under the Apache License, Version 2.0 (the
007     *  "License"); you may not use this file except in compliance
008     *  with the License.  You may obtain a copy of the License at
009     *  
010     *    http://www.apache.org/licenses/LICENSE-2.0
011     *  
012     *  Unless required by applicable law or agreed to in writing,
013     *  software distributed under the License is distributed on an
014     *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     *  KIND, either express or implied.  See the License for the
016     *  specific language governing permissions and limitations
017     *  under the License. 
018     *  
019     */
020    package org.apache.directory.studio.apacheds.model;
021    
022    
023    import java.io.File;
024    import java.io.FileInputStream;
025    import java.io.FileNotFoundException;
026    import java.io.FileOutputStream;
027    import java.io.IOException;
028    import java.io.InputStream;
029    import java.io.OutputStream;
030    import java.util.ArrayList;
031    import java.util.HashMap;
032    import java.util.List;
033    import java.util.Map;
034    
035    import org.apache.commons.io.FileUtils;
036    import org.apache.directory.studio.apacheds.ApacheDsPlugin;
037    import org.apache.directory.studio.apacheds.ApacheDsPluginUtils;
038    import org.eclipse.core.runtime.IPath;
039    
040    
041    /**
042     * This class implements the servers handler.
043     * <p>
044     * 
045     * It is used to store all the servers used in the plugin.
046     *
047     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
048     * @version $Rev$, $Date$
049     */
050    public class ServersHandler
051    {
052        /** The default instance */
053        private static ServersHandler instance;
054    
055        /** The list of servers */
056        private List<Server> serversList;
057    
058        /** The map of servers identified by ID */
059        private Map<String, Server> serversIdMap;
060    
061        /** The listeners */
062        private List<ServersHandlerListener> listeners;
063    
064    
065        /**
066         * Creates a new instance of ServersHandler.
067         */
068        private ServersHandler()
069        {
070            // Initializing lists and maps
071            serversList = new ArrayList<Server>();
072            serversIdMap = new HashMap<String, Server>();
073            listeners = new ArrayList<ServersHandlerListener>();
074        }
075    
076    
077        /**
078         * Gets the default servers handler (singleton pattern).
079         *
080         * @return
081         *      the default servers handler
082         */
083        public static ServersHandler getDefault()
084        {
085            if ( instance == null )
086            {
087                instance = new ServersHandler();
088            }
089    
090            return instance;
091        }
092    
093    
094        /**
095         * Adds a server.
096         *
097         * @param server
098         *      the server to be added
099         */
100        public void addServer( Server server )
101        {
102            addServer( server, true );
103    
104            saveServersToStore();
105        }
106    
107    
108        /**
109         * Adds a server.
110         *
111         * @param server
112         *      the server to be added
113         * @param notifyListeners
114         *      <code>true</code> if the listeners need to be notified, 
115         *      <code>false</code> if not.
116         */
117        private void addServer( Server server, boolean notifyListeners )
118        {
119            if ( !serversList.contains( server ) )
120            {
121                // Adding the server
122                serversList.add( server );
123                serversIdMap.put( server.getId(), server );
124    
125                // Notifying listeners
126                if ( notifyListeners )
127                {
128                    for ( ServersHandlerListener listener : listeners.toArray( new ServersHandlerListener[0] ) )
129                    {
130                        listener.serverAdded( server );
131                    }
132                }
133            }
134        }
135    
136    
137        /**
138         * Removes a server.
139         *
140         * @param server
141         *      the server to be removed
142         */
143        public void removeServer( Server server )
144        {
145            removeServer( server, true );
146    
147            saveServersToStore();
148        }
149    
150    
151        /**
152         * Removes a server.
153         *
154         * @param server
155         *      the server to be removed
156         * @param notifyListeners
157         *      <code>true</code> if the listeners need to be notified, 
158         *      <code>false</code> if not.
159         */
160        private void removeServer( Server server, boolean notifyListeners )
161        {
162            if ( serversList.contains( server ) )
163            {
164                // Removing the server
165                serversList.remove( server );
166                serversIdMap.remove( server.getId() );
167    
168                // Notifying listeners
169                if ( notifyListeners )
170                {
171                    for ( ServersHandlerListener listener : listeners.toArray( new ServersHandlerListener[0] ) )
172                    {
173                        listener.serverRemoved( server );
174                    }
175                }
176            }
177        }
178    
179    
180        /**
181         * Indicates if the server handler contains the given server.
182         *
183         * @param server
184         *      the server
185         * @return
186         *      <code>true</code> if the server hander contains the given server, 
187         *      <code>false</code> if not
188         */
189        public boolean containsServer( Server server )
190        {
191            return serversList.contains( server );
192        }
193    
194    
195        /**
196         * Adds a listener to the servers handler.
197         *
198         * @param listener
199         *      the listener to add
200         */
201        public void addListener( ServersHandlerListener listener )
202        {
203            if ( !listeners.contains( listener ) )
204            {
205                listeners.add( listener );
206            }
207        }
208    
209    
210        /**
211         * Removes a listener to the servers handler.
212         *
213         * @param listener
214         *      the listener to remove
215         */
216        public void removeListener( ServersHandlerListener listener )
217        {
218            if ( listeners.contains( listener ) )
219            {
220                listeners.remove( listener );
221            }
222        }
223    
224    
225        /**
226         * Loads the server from the file store.
227         */
228        public void loadServersFromStore()
229        {
230            File store = getServersStorePath().toFile();
231            File tempStore = getServersStoreTempPath().toFile();
232            boolean loadFailed = false;
233            String exceptionMessage = ""; //$NON-NLS-1$
234    
235            // We try to load the servers file
236            if ( store.exists() )
237            {
238                try
239                {
240                    InputStream inputStream = new FileInputStream( store );
241                    List<Server> servers = ServersHandlerIO.read( inputStream );
242                    for ( Server server : servers )
243                    {
244                        addServer( server, false );
245                    }
246                    return;
247                }
248                catch ( FileNotFoundException e )
249                {
250                    loadFailed = true;
251                    exceptionMessage = e.getMessage();
252                }
253                catch ( ServersHandlerIOException e )
254                {
255                    loadFailed = true;
256                    exceptionMessage = e.getMessage();
257                }
258    
259                if ( loadFailed )
260                {
261                    if ( tempStore.exists() )
262                    {
263                        // If something went wrong, we try to load the temp servers file
264                        try
265                        {
266                            InputStream inputStream = new FileInputStream( tempStore );
267                            List<Server> servers = ServersHandlerIO.read( inputStream );
268                            for ( Server server : servers )
269                            {
270                                addServer( server, false );
271                            }
272                            return;
273                        }
274                        catch ( FileNotFoundException e )
275                        {
276                            ApacheDsPluginUtils.reportError( Messages.getString( "ServersHandler.ErrorLoadingServer" ) //$NON-NLS-1$
277                                + e.getMessage() );
278                        }
279                        catch ( ServersHandlerIOException e )
280                        {
281                            ApacheDsPluginUtils.reportError( Messages.getString( "ServersHandler.ErrorLoadingServer" ) //$NON-NLS-1$
282                                + e.getMessage() );
283                        }
284                    }
285                    else
286                    {
287                        ApacheDsPluginUtils.reportError( Messages.getString( "ServersHandler.ErrorLoadingServer" ) //$NON-NLS-1$
288                            + exceptionMessage );
289                    }
290                }
291            }
292        }
293    
294    
295        /**
296         * Saves the server to the file store.
297         */
298        public void saveServersToStore()
299        {
300            File store = getServersStorePath().toFile();
301            File tempStore = getServersStoreTempPath().toFile();
302            boolean saveFailed = false;
303    
304            try
305            {
306                // Saving the servers to the temp servers file
307                OutputStream outputStream = new FileOutputStream( tempStore );
308                ServersHandlerIO.write( serversList, outputStream );
309    
310                // Copying the temp servers file to the final location
311                String content = FileUtils.readFileToString( tempStore, "UTF-8" ); //$NON-NLS-1$
312                FileUtils.writeStringToFile( store, content, "UTF-8" ); //$NON-NLS-1$
313            }
314            catch ( FileNotFoundException e )
315            {
316                saveFailed = true;
317            }
318            catch ( IOException e )
319            {
320                saveFailed = true;
321            }
322    
323            if ( saveFailed )
324            {
325                // If an error occurs when saving to the temp servers file or
326                // when copying the temp servers file to the final location,
327                // we try to save the servers directly to the final location.
328                try
329                {
330                    // Saving the servers to the temp servers file
331                    OutputStream outputStream = new FileOutputStream( store );
332                    ServersHandlerIO.write( serversList, outputStream );
333                }
334                catch ( FileNotFoundException e )
335                {
336                    ApacheDsPluginUtils
337                        .reportError( Messages.getString( "ServersHandler.ErrorLoadingServer" ) + e.getMessage() ); //$NON-NLS-1$
338                }
339                catch ( IOException e )
340                {
341                    ApacheDsPluginUtils
342                        .reportError( Messages.getString( "ServersHandler.ErrorLoadingServer" ) + e.getMessage() ); //$NON-NLS-1$
343                }
344            }
345        }
346    
347    
348        /**
349         * Gets the path to the server file.
350         *
351         * @return
352         *      the path to the server file.
353         */
354        private IPath getServersStorePath()
355        {
356            return ApacheDsPlugin.getDefault().getStateLocation().append( "servers.xml" ); //$NON-NLS-1$
357        }
358    
359    
360        /**
361         * Gets the path to the server temp file.
362         *
363         * @return
364         *      the path to the server temp file.
365         */
366        private IPath getServersStoreTempPath()
367        {
368            return ApacheDsPlugin.getDefault().getStateLocation().append( "servers-temp.xml" ); //$NON-NLS-1$
369        }
370    
371    
372        /**
373         * Indicates if the given is available (i.e. not already taken by another 
374         * server).
375         *
376         * @param name
377         *      the name
378         * @return
379         *      <code>true</code> if the name is available, <code>false</code> if
380         *      not
381         */
382        public boolean isNameAvailable( String name )
383        {
384            for ( Server server : serversList )
385            {
386                if ( server.getName().equalsIgnoreCase( name ) )
387                {
388                    return false;
389                }
390            }
391    
392            return true;
393        }
394    
395    
396        /**
397         * Gets the servers list.
398         *
399         * @return
400         *      the servers list.
401         */
402        public List<Server> getServersList()
403        {
404            return serversList;
405        }
406    
407    
408        /**
409         * Gets the server associated with the given id.
410         *
411         * @return
412         *      the server associated witht the given id.
413         */
414        public Server getServerById( String id )
415        {
416            return serversIdMap.get( id );
417        }
418    }