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 }