KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > enterprise > admin > server > core > channel > AdminChannelServer


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23 package com.sun.enterprise.admin.server.core.channel;
24
25 import java.io.File JavaDoc;
26 import java.io.FileInputStream JavaDoc;
27 import java.io.IOException JavaDoc;
28 import java.net.InetAddress JavaDoc;
29 import java.net.UnknownHostException JavaDoc;
30 import java.rmi.NoSuchObjectException JavaDoc;
31 import java.rmi.RemoteException JavaDoc;
32 import java.rmi.server.RemoteObject JavaDoc;
33 import java.rmi.server.RemoteStub JavaDoc;
34 import java.rmi.server.RMIClientSocketFactory JavaDoc;
35 import java.rmi.server.RMIServerSocketFactory JavaDoc;
36 import java.rmi.server.ServerNotActiveException JavaDoc;
37 import java.rmi.server.UnicastRemoteObject JavaDoc;
38
39 import com.sun.enterprise.admin.common.Status;
40 import com.sun.enterprise.admin.event.AdminEvent;
41 import com.sun.enterprise.admin.event.AdminEventMulticaster;
42 import com.sun.enterprise.admin.event.AdminEventResult;
43 import com.sun.enterprise.server.ss.ASSocketService;
44
45 //i18n import
46
import com.sun.enterprise.util.i18n.StringManager;
47
48 /**
49  * RMI server object for admin channel.
50  */

51 public class AdminChannelServer extends UnicastRemoteObject JavaDoc
52         implements RemoteAdminChannel {
53
54     private String JavaDoc localAddress = null;
55
56     private byte[] myKey;
57
58     /**
59      * Server instance status. Its value is one of the constant <code>
60      * kInstanceStartingCode, kInstanceRunningCode or kInstanceStoppingCode
61      * </code> from the class <code>com.sun.enterprise.admin.common.Status</code>.
62      */

63     private int instanceStatus = Status.kInstanceStartingCode;
64
65     /**
66      * Is restart needed on this server instance to sync it up with persistent
67      * configuration.
68      */

69     private boolean restartNeeded = false;
70
71     private int conflictedPort = 0;
72
73     /**
74      * Create a new RMI server object for admin channel
75      */

76     public AdminChannelServer() throws RemoteException JavaDoc {
77         super();
78
79         // read from the persisted state
80
restartNeeded = RRStateFactory.getState();
81     }
82
83     /**
84      * Create a new RMI server object for admin channel that uses specified
85      * socket factories.
86      */

87     public AdminChannelServer(int port, RMIClientSocketFactory JavaDoc csf,
88             RMIServerSocketFactory JavaDoc ssf) throws RemoteException JavaDoc {
89         super(port, csf, ssf);
90
91         // read from the persisted state
92
restartNeeded = RRStateFactory.getState();
93     }
94
95     /**
96      * Send event notification.
97      */

98     public AdminEventResult sendNotification(byte[] key, AdminEvent event)
99             throws RemoteException JavaDoc {
100         if (!checkAccess()) {
101             String JavaDoc msg = localStrings.getString( "admin.server.core.channel.unauthorized_access" );
102             throw new SecurityException JavaDoc( msg );
103         }
104         if (!keyMatches(key)) {
105             String JavaDoc msg = localStrings.getString( "admin.server.core.channel.invalid_key" );
106             throw new IllegalArgumentException JavaDoc( msg );
107         }
108         return AdminEventMulticaster.multicastEvent(event);
109     }
110
111     /**
112      * Ping server. If the method call succeeds, notifications can be sent.
113      */

114     public boolean pingServer(byte[] key) throws RemoteException JavaDoc {
115         if (!checkAccess()) {
116             String JavaDoc msg = localStrings.getString( "admin.server.core.channel.unauthorized_access" );
117             throw new SecurityException JavaDoc( msg );
118         }
119         if (!keyMatches(key)) {
120             String JavaDoc msg = localStrings.getString( "admin.server.core.channel.invalid_key" );
121             throw new IllegalArgumentException JavaDoc( msg );
122         }
123         return true;
124     }
125
126     /**
127      * Get server status code. This method will return one of the following
128      * constants from class <code>com.sun.enterprise.admin.common.Status</code>
129      * -- <code>kInstanceStartingCode, kInstanceRunningCode or
130      * kInstanceStoppingCode</code> representing starting, running and stopping
131      * condition for the instance.
132      * @param key shared secret
133      * @returns server status code denoting whether server is starting,
134      * running or stopping.
135      */

136     public int getServerStatusCode(byte[] key) throws RemoteException JavaDoc {
137         if (!checkAccess()) {
138             String JavaDoc msg = localStrings.getString( "admin.server.core.channel.unauthorized_access" );
139             throw new SecurityException JavaDoc( msg );
140         }
141         if (!keyMatches(key)) {
142             String JavaDoc msg = localStrings.getString( "admin.server.core.channel.invalid_key" );
143             throw new IllegalArgumentException JavaDoc( msg );
144         }
145         return instanceStatus;
146     }
147
148     /**
149      * Is restart needed to use persistent server configuration. After a
150      * notification, the server may be in inconsistenet state with respect
151      * to persistent configuration because all changes to configuration can
152      * not be handled dynamically - A restart is needed in such cases to
153      * synchronize server with persistent configuration.
154      * @param key shared secret
155      * @return true if restart is required, false otherwise.
156      */

157     public boolean isRestartNeeded(byte[] key) throws RemoteException JavaDoc {
158         if (!checkAccess()) {
159             String JavaDoc msg = localStrings.getString( "admin.server.core.channel.unauthorized_access" );
160             throw new SecurityException JavaDoc( msg );
161         }
162         if (!keyMatches(key)) {
163             String JavaDoc msg = localStrings.getString( "admin.server.core.channel.invalid_key" );
164             throw new IllegalArgumentException JavaDoc( msg );
165         }
166         return restartNeeded;
167     }
168
169     /**
170      * Set restart needed status on server instance.
171      * @param key shared secret
172      * @param needRestart true if the instance should be restarted to use
173      * changes in persistent configuration.
174      */

175     public void setRestartNeeded(byte[] key, boolean needRestart)
176             throws RemoteException JavaDoc {
177         if (!checkAccess()) {
178             String JavaDoc msg = localStrings.getString( "admin.server.core.channel.unauthorized_access" );
179             throw new SecurityException JavaDoc( msg );
180         }
181         if (!keyMatches(key)) {
182             String JavaDoc msg = localStrings.getString( "admin.server.core.channel.invalid_key" );
183             throw new IllegalArgumentException JavaDoc( msg );
184         }
185
186         try {
187             // persists the state to a file
188
RRStateFactory.saveState(needRestart);
189         } catch (IOException JavaDoc ioe) {
190             String JavaDoc msg = localStrings.getString(
191                 "admin.server.core.channel.unable_saving_state_file");
192             throw new RuntimeException JavaDoc(msg, ioe);
193         }
194
195         restartNeeded = needRestart;
196     }
197
198     /**
199      * Returns the port number that caused conflict. This could be
200      * 0, if port-conflict is not the cause of failure.
201      * @param key shared secret
202      * @return port number.
203      */

204     public int getConflictedPort(byte[] key) {
205         if (!checkAccess()) {
206                         String JavaDoc msg = localStrings.getString( "admin.server.core.channel.unauthorized_access" );
207             throw new SecurityException JavaDoc( msg );
208         }
209         if (!keyMatches(key)) {
210                         String JavaDoc msg = localStrings.getString( "admin.server.core.channel.invalid_key" );
211             throw new IllegalArgumentException JavaDoc( msg );
212         }
213         return conflictedPort;
214     }
215
216     /**
217      * Client will exit after calling this method. Notify the lock held
218      * in ASSocketService.
219      * @param key shared secret
220      */

221     public void triggerServerExit(byte[] key) {
222         if (!checkAccess()) {
223                         String JavaDoc msg = localStrings.getString( "admin.server.core.channel.unauthorized_access" );
224             throw new SecurityException JavaDoc( msg );
225         }
226         if (!keyMatches(key)) {
227                         String JavaDoc msg = localStrings.getString( "admin.server.core.channel.invalid_key" );
228             throw new IllegalArgumentException JavaDoc( msg );
229         }
230         ASSocketService.triggerServerExit();
231     }
232
233     /**
234      * Set shared secret that clients must specify in every remote call. This
235      * is set at startup.
236      */

237     void setSharedInfo(byte[] seed) {
238         myKey = seed;
239     }
240
241     /**
242      * Get remote stub for the server object.
243      */

244     RemoteStub JavaDoc getRemoteStub() throws NoSuchObjectException JavaDoc {
245         return (RemoteStub JavaDoc)RemoteObject.toStub(this);
246     }
247
248     /**
249      * Set the address that clients will be checked against. This is set at
250      * startup.
251      */

252     void setLocalAddress(InetAddress JavaDoc address) {
253         localAddress = address.getHostAddress();
254     }
255
256     /**
257      * Set channel to starting state.
258      */

259     void setChannelStarting() {
260         this.instanceStatus = Status.kInstanceStartingCode;
261     }
262
263     /**
264      * Set channel to ready (running) state.
265      */

266     void setChannelReady() {
267         this.instanceStatus = Status.kInstanceRunningCode;
268     }
269
270     /**
271      * Set channel to stopping state.
272      */

273     void setChannelStopping() {
274         this.instanceStatus = Status.kInstanceStoppingCode;
275     }
276
277     /**
278      * Set the channel to failed state.
279      *
280      * @conflictedPort Port that causing conflict. This could be 0
281      * if the reason for failure is not port-conflict.
282      */

283     void setChannelAborting(int conflictedPort) {
284         this.conflictedPort = conflictedPort;
285         this.instanceStatus = Status.kInstanceFailedCode;
286     }
287
288     /**
289      * Verify that client is coming from the same IP address as the server.
290      */

291     private boolean checkAccess() {
292         boolean allowed = true;
293         String JavaDoc addr = null;
294         if (AdminChannel.LOCAL_ONLY_ACCESS.equals(AdminChannel.getAccessLevel())) {
295             boolean matchAddress = true;
296             try {
297                 addr = this.getClientHost();
298                 if (addr == null) {
299                     AdminChannel.warn(CLIENT_HOST_NULL);
300                     allowed = false;
301                     matchAddress = false;
302                 }
303             } catch (ServerNotActiveException JavaDoc snae) {
304                 AdminChannel.warn(LOCAL_ACCESS);
305                 AdminChannel.debug(snae);
306                 matchAddress = false;
307             }
308             if (matchAddress) {
309                 allowed = addressMatches(addr);
310             }
311         }
312         if (!allowed) {
313             AdminChannel.debug(ADDR_MISMATCH,
314                     new Object JavaDoc[] {addr, getLocalAddress()});
315         }
316         return allowed;
317     }
318
319     /**
320      * Check whether local address of the server object is same as specified
321      * address.
322      */

323     private boolean addressMatches(String JavaDoc addr) {
324         String JavaDoc localAddr = getLocalAddress();
325         if (localAddr == null) {
326             return false;
327         }
328         return addr.equals(localAddr);
329     }
330
331     /**
332      * Get local address for the server object. If local address has not been
333      * initialized, it is initialized using <code>InetAddress.getLocalHost()
334      * </code>.
335      */

336     private String JavaDoc getLocalAddress() {
337         if (localAddress == null) {
338             InetAddress JavaDoc inetAddr = null;
339             try {
340                 inetAddr = InetAddress.getLocalHost();
341             } catch (UnknownHostException JavaDoc uhe) {
342                 AdminChannel.warn(NO_LOCAL_HOST);
343                 AdminChannel.debug(uhe);
344             }
345             if (inetAddr != null) {
346                 localAddress = inetAddr.getHostAddress();
347             }
348         }
349         return localAddress;
350     }
351
352     /**
353      * Check whether shared secret for the server object matches the specified
354      * key.
355      */

356     private boolean keyMatches(byte[] key) {
357         boolean matches = true;
358         if (AdminChannel.ENFORCE.equals(AdminChannel.getKeyCheckLevel())) {
359             matches = checkKeyLength(key);
360             for (int i = 0; matches && i < AdminChannel.SEED_LENGTH; i++) {
361                 if (key[i] != myKey[i]) {
362                     matches = false;
363                 }
364             }
365         } else if (AdminChannel.REQUIRE_KEY.equals(AdminChannel.getKeyCheckLevel())) {
366             matches = checkKeyLength(key);
367         }
368         if (!matches) {
369             AdminChannel.debug(KEY_MISMATCH,
370                     new Object JavaDoc[] {new String JavaDoc(key), new String JavaDoc(myKey)});
371         }
372         return matches;
373     }
374
375     /**
376      * Check whether specified key is of correct length.
377      */

378     private boolean checkKeyLength(byte[] key) {
379         return (key.length == AdminChannel.SEED_LENGTH);
380     }
381
382     private final static String JavaDoc CLIENT_HOST_NULL = "channel.client_host_null";
383     private final static String JavaDoc LOCAL_ACCESS = "channel.local_access";
384     private final static String JavaDoc ADDR_MISMATCH = "channel.addr_mismatch";
385     private final static String JavaDoc NO_LOCAL_HOST = "channel.no_local_host";
386     private final static String JavaDoc KEY_MISMATCH = "channel.key_mismatch";
387
388     // i18n StringManager
389
private static StringManager localStrings =
390         StringManager.getManager( AdminChannelServer.class );
391 }
392
Popular Tags