View Javadoc
1   package org.andromda.core.server;
2   
3   import java.io.DataInputStream;
4   import java.io.IOException;
5   import java.io.ObjectInputStream;
6   import java.io.ObjectOutputStream;
7   import java.net.ServerSocket;
8   import java.net.Socket;
9   import java.net.SocketTimeoutException;
10  import org.andromda.core.common.AndroMDALogger;
11  import org.andromda.core.configuration.Configuration;
12  import org.andromda.core.engine.Engine;
13  
14  /**
15   * The default AndroMDA {@link Server instance}.
16   *
17   * @author Chad Brandon
18   */
19  public class DefaultServer
20      implements Server
21  {
22      /**
23       * The message sent to the client when AndroMDA processing has completed.
24       */
25      private static final String COMPLETE = "complete";
26  
27      /**
28       * The command sent to the server that indicates it
29       * should stop.
30       */
31      static final String STOP = "stop";
32  
33      /**
34       * The server listener.
35       */
36      private ServerSocket listener = null;
37  
38      /**
39       * The AndroMDA Engine instance.
40       */
41      private Engine engine = Engine.newInstance();
42  
43      /**
44       * @see org.andromda.core.server.Server#start(org.andromda.core.configuration.Configuration)
45       */
46      public void start(final Configuration configuration)
47      {
48          engine.initialize(configuration);
49          if (configuration != null)
50          {
51              final org.andromda.core.configuration.Server serverConfiguration = configuration.getServer();
52              if (serverConfiguration != null)
53              {
54                  try
55                  {
56                      try
57                      {
58                          this.listener = new ServerSocket(serverConfiguration.getPort());
59                          final int modelLoadInterval = serverConfiguration.getLoadInterval();
60                          if (modelLoadInterval > 0)
61                          {
62                              this.listener.setSoTimeout(serverConfiguration.getLoadInterval());
63                          }
64                      }
65                      catch (final IOException exception)
66                      {
67                          throw new ServerException(
68                              "Could not listen on port '" + serverConfiguration.getPort() +
69                              "', change the port in your configuration");
70                      }
71                      while (true)
72                      {
73                          try
74                          {
75                              final Socket client = this.listener.accept();
76                              if (client != null)
77                              {
78                                  final ObjectOutputStream serverOutput =
79                                      new ObjectOutputStream(client.getOutputStream());
80                                  final ObjectInputStream objectInput =
81                                      new ObjectInputStream(new DataInputStream(client.getInputStream()));
82                                  try
83                                  {
84                                      final Object object = objectInput.readObject();
85                                      if (object instanceof Configuration)
86                                      {
87                                          this.engine.run((Configuration)object, false, null);
88                                      }
89                                      else if (object instanceof String)
90                                      {
91                                          final String string = (String)object;
92                                          if (string.equals(STOP))
93                                          {
94                                              break;
95                                          }
96                                      }
97                                  }
98                                  catch (final Throwable throwable)
99                                  {
100                                     AndroMDALogger.error(throwable);
101 
102                                     // - pass the exception to the client
103                                     serverOutput.writeObject(throwable);
104                                 }
105 
106                                 // - signal to the client, it can stop waiting
107                                 serverOutput.writeObject(COMPLETE);
108                                 serverOutput.flush();
109                                 serverOutput.close();
110                                 objectInput.close();
111                                 client.close();
112                             }
113                         }
114                         catch (final SocketTimeoutException exception)
115                         {
116                             try
117                             {
118                                 this.engine.loadModelsIfNecessary(configuration);
119                                 this.resetFailedLoadAttempts();
120                             }
121                             catch (final Throwable throwable)
122                             {
123                                 this.incrementFailedLoadAttempts();
124 
125                                 // - only fail if the failed load attempts is greater than the maximum
126                                 if (this.failedLoadAttempts > serverConfiguration.getMaximumFailedLoadAttempts())
127                                 {
128                                     throw throwable;
129                                 }
130                             }
131                         }
132                     }
133                     this.shutdown();
134                 }
135                 catch (final Throwable throwable)
136                 {
137                     throw new ServerException(throwable);
138                 }
139             }
140         }
141     }
142 
143     /**
144      * Stores the failed load attempts.
145      */
146     private int failedLoadAttempts;
147 
148     /**
149      * Resets the failed load attempt counter.
150      */
151     private void resetFailedLoadAttempts()
152     {
153         this.failedLoadAttempts = 0;
154     }
155 
156     /**
157      * Increments the failed load attempt counter.
158      */
159     private void incrementFailedLoadAttempts()
160     {
161         this.failedLoadAttempts++;
162     }
163 
164     /**
165      * Shuts the server down.
166      */
167     public void shutdown()
168     {
169         try
170         {
171             this.listener.close();
172             this.listener = null;
173             this.engine.shutdown();
174         }
175         catch (final IOException exception)
176         {
177             // ignore exception
178         }
179     }
180 }