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                    outputStream.close();
334                }
335                catch ( FileNotFoundException e )
336                {
337                    ApacheDsPluginUtils
338                        .reportError( Messages.getString( "ServersHandler.ErrorLoadingServer" ) + e.getMessage() ); //$NON-NLS-1$
339                }
340                catch ( IOException e )
341                {
342                    ApacheDsPluginUtils
343                        .reportError( Messages.getString( "ServersHandler.ErrorLoadingServer" ) + e.getMessage() ); //$NON-NLS-1$
344                }
345            }
346        }
347    
348    
349        /**
350         * Gets the path to the server file.
351         *
352         * @return
353         *      the path to the server file.
354         */
355        private IPath getServersStorePath()
356        {
357            return ApacheDsPlugin.getDefault().getStateLocation().append( "servers.xml" ); //$NON-NLS-1$
358        }
359    
360    
361        /**
362         * Gets the path to the server temp file.
363         *
364         * @return
365         *      the path to the server temp file.
366         */
367        private IPath getServersStoreTempPath()
368        {
369            return ApacheDsPlugin.getDefault().getStateLocation().append( "servers-temp.xml" ); //$NON-NLS-1$
370        }
371    
372    
373        /**
374         * Indicates if the given is available (i.e. not already taken by another 
375         * server).
376         *
377         * @param name
378         *      the name
379         * @return
380         *      <code>true</code> if the name is available, <code>false</code> if
381         *      not
382         */
383        public boolean isNameAvailable( String name )
384        {
385            for ( Server server : serversList )
386            {
387                if ( server.getName().equalsIgnoreCase( name ) )
388                {
389                    return false;
390                }
391            }
392    
393            return true;
394        }
395    
396    
397        /**
398         * Gets the servers list.
399         *
400         * @return
401         *      the servers list.
402         */
403        public List<Server> getServersList()
404        {
405            return serversList;
406        }
407    
408    
409        /**
410         * Gets the server associated with the given id.
411         *
412         * @return
413         *      the server associated witht the given id.
414         */
415        public Server getServerById( String id )
416        {
417            return serversIdMap.get( id );
418        }
419    }