1/*
2 * Copyright (c) 1997, 2004, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package com.sun.corba.se.impl.activation;
27
28import java.io.File;
29import java.io.FileInputStream;
30import java.io.FileOutputStream;
31import java.io.ObjectInputStream;
32import java.io.ObjectOutputStream;
33import java.io.Serializable;
34import java.util.Properties;
35import java.util.Hashtable;
36import java.util.Enumeration;
37import java.util.Vector;
38
39import org.omg.CORBA.CompletionStatus;
40import org.omg.CORBA.INITIALIZE;
41import org.omg.CORBA.INTERNAL;
42import org.omg.CORBA.SystemException;
43
44import com.sun.corba.se.spi.activation.BadServerDefinition;
45import com.sun.corba.se.spi.activation.RepositoryPackage.ServerDef;
46import com.sun.corba.se.spi.activation._RepositoryImplBase;
47import com.sun.corba.se.spi.activation.ServerAlreadyRegistered;
48import com.sun.corba.se.spi.activation.ServerAlreadyInstalled;
49import com.sun.corba.se.spi.activation.ServerAlreadyUninstalled;
50import com.sun.corba.se.spi.activation.ServerNotRegistered;
51import com.sun.corba.se.spi.legacy.connection.LegacyServerSocketEndPointInfo;
52import com.sun.corba.se.spi.transport.SocketOrChannelAcceptor;
53import com.sun.corba.se.spi.orb.ORB;
54import com.sun.corba.se.impl.orbutil.ORBConstants;
55
56import com.sun.corba.se.spi.logging.CORBALogDomains;
57import com.sun.corba.se.impl.logging.ActivationSystemException;
58
59/**
60 *
61 * @author      Rohit Garg
62 * @since       JDK1.2
63 */
64public class RepositoryImpl extends _RepositoryImplBase
65    implements Serializable
66{
67
68    // added serialver computed by the tool
69    private static final long serialVersionUID = 8458417785209341858L;
70
71    RepositoryImpl(ORB orb, File dbDir, boolean debug)
72    {
73        this.debug = debug ;
74        this.orb = orb;
75        wrapper = ActivationSystemException.get( orb, CORBALogDomains.ORBD_REPOSITORY ) ;
76
77        // if databse does not exist, create it otherwise read it in
78        File dbFile = new File(dbDir, "servers.db");
79        if (!dbFile.exists()) {
80            db = new RepositoryDB(dbFile);
81            db.flush();
82        } else {
83            try {
84                FileInputStream fis = new FileInputStream(dbFile);
85                ObjectInputStream ois = new ObjectInputStream(fis);
86                db = (RepositoryDB) ois.readObject();
87                ois.close();
88            } catch (Exception e) {
89                throw wrapper.cannotReadRepositoryDb( e ) ;
90            }
91        }
92
93        // export the repository
94        orb.connect(this);
95    }
96
97    private String printServerDef( ServerDef sd )
98    {
99        return "ServerDef[applicationName=" + sd.applicationName +
100            " serverName=" + sd.serverName +
101            " serverClassPath=" + sd.serverClassPath +
102            " serverArgs=" + sd. serverArgs +
103            " serverVmArgs=" + sd.serverVmArgs +
104            "]" ;
105    }
106
107    public int registerServer(ServerDef serverDef, int theServerId)
108        throws ServerAlreadyRegistered
109    {
110        int         serverId;
111        DBServerDef server = null;
112
113        synchronized (db) {
114
115            // check if server already registered
116            Enumeration enumeration = db.serverTable.elements();
117            while (enumeration.hasMoreElements()) {
118                server = (DBServerDef) enumeration.nextElement();
119                if (serverDef.applicationName.equals(server.applicationName)) {
120                    if (debug)
121                        System.out.println(
122                            "RepositoryImpl: registerServer called " +
123                            "to register ServerDef " +
124                            printServerDef( serverDef ) +
125                            " with " + ((theServerId==illegalServerId) ?
126                        "a new server Id" : ("server Id " + theServerId)) +
127                                           " FAILED because it is already registered." ) ;
128
129                    throw (new ServerAlreadyRegistered(server.id));
130                }
131            }
132
133            // generate a new server id
134            if (theServerId == illegalServerId)
135                serverId = db.incrementServerIdCounter();
136            else
137                serverId = theServerId;
138
139            // add server def to the database
140            server = new DBServerDef(serverDef, serverId);
141            db.serverTable.put(new Integer(serverId), server);
142            db.flush();
143
144            if (debug)
145                if (theServerId==illegalServerId)
146                    System.out.println( "RepositoryImpl: registerServer called " +
147                                        "to register ServerDef " + printServerDef( serverDef ) +
148                                        " with new serverId " + serverId ) ;
149                else
150                    System.out.println( "RepositoryImpl: registerServer called " +
151                                        "to register ServerDef " + printServerDef( serverDef ) +
152                                        " with assigned serverId " + serverId ) ;
153
154            return serverId;
155        }
156    }
157
158    public int registerServer(ServerDef serverDef)
159        throws ServerAlreadyRegistered, BadServerDefinition
160    {
161        // verify that the entry is valid
162        LegacyServerSocketEndPointInfo endpoint =
163            orb.getLegacyServerSocketManager()
164                .legacyGetEndpoint(LegacyServerSocketEndPointInfo.BOOT_NAMING);
165        int initSvcPort = ((SocketOrChannelAcceptor)endpoint)
166            .getServerSocket().getLocalPort();
167        ServerTableEntry entry = new ServerTableEntry( wrapper,
168            illegalServerId, serverDef, (int) initSvcPort, "", true, debug );
169
170        switch (entry.verify()) {
171        case ServerMain.OK:
172            break;
173        case ServerMain.MAIN_CLASS_NOT_FOUND:
174            throw new BadServerDefinition("main class not found.");
175        case ServerMain.NO_MAIN_METHOD:
176            throw new BadServerDefinition("no main method found.");
177        case ServerMain.APPLICATION_ERROR:
178            throw new BadServerDefinition("server application error.");
179        default:
180            throw new BadServerDefinition("unknown Exception.");
181        }
182
183        return registerServer(serverDef, illegalServerId);
184    }
185
186    public void unregisterServer(int serverId) throws ServerNotRegistered {
187
188        DBServerDef server = null;
189        Integer id = new Integer(serverId);
190
191        synchronized (db) {
192
193            // check to see if the server is registered
194            server = (DBServerDef) db.serverTable.get(id);
195            if (server == null)  {
196                if (debug)
197                    System.out.println(
198                                       "RepositoryImpl: unregisterServer for serverId " +
199                                       serverId + " called: server not registered" ) ;
200
201                throw (new ServerNotRegistered());
202            }
203
204            // remove server from the database
205            db.serverTable.remove(id);
206            db.flush();
207        }
208
209        if (debug)
210            System.out.println(
211                               "RepositoryImpl: unregisterServer for serverId " + serverId +
212                               " called" ) ;
213    }
214
215    private DBServerDef getDBServerDef(int serverId) throws ServerNotRegistered
216    {
217        Integer id = new Integer(serverId);
218        DBServerDef server = (DBServerDef) db.serverTable.get(id);
219
220        if (server == null)
221            throw new ServerNotRegistered( serverId );
222
223        return server ;
224    }
225
226    public ServerDef getServer(int serverId) throws ServerNotRegistered
227    {
228        DBServerDef server = getDBServerDef( serverId ) ;
229
230        ServerDef serverDef = new ServerDef(server.applicationName, server.name,
231                                            server.classPath, server.args, server.vmArgs);
232
233        if (debug)
234            System.out.println(
235                               "RepositoryImpl: getServer for serverId " + serverId +
236                               " returns " + printServerDef( serverDef ) ) ;
237
238        return serverDef;
239    }
240
241    public boolean isInstalled(int serverId) throws ServerNotRegistered {
242        DBServerDef server = getDBServerDef( serverId ) ;
243        return server.isInstalled ;
244    }
245
246    public void install( int serverId )
247        throws ServerNotRegistered, ServerAlreadyInstalled
248    {
249        DBServerDef server = getDBServerDef( serverId ) ;
250
251        if (server.isInstalled)
252            throw new ServerAlreadyInstalled( serverId ) ;
253        else {
254            server.isInstalled = true ;
255            db.flush() ;
256        }
257    }
258
259    public void uninstall( int serverId )
260        throws ServerNotRegistered, ServerAlreadyUninstalled
261    {
262        DBServerDef server = getDBServerDef( serverId ) ;
263
264        if (!server.isInstalled)
265            throw new ServerAlreadyUninstalled( serverId ) ;
266        else {
267            server.isInstalled = false ;
268            db.flush() ;
269        }
270    }
271
272    public int[] listRegisteredServers() {
273        synchronized (db) {
274            int i=0;
275
276            int servers[] = new int[db.serverTable.size()];
277
278            Enumeration enumeration = db.serverTable.elements();
279
280            while (enumeration.hasMoreElements()) {
281                DBServerDef server = (DBServerDef) enumeration.nextElement();
282                servers[i++] = server.id;
283            }
284
285            if (debug) {
286                StringBuffer sb = new StringBuffer() ;
287                for (int ctr=0; ctr<servers.length; ctr++) {
288                    sb.append( ' ' ) ;
289                    sb.append( servers[ctr] ) ;
290                }
291
292                System.out.println(
293                                   "RepositoryImpl: listRegisteredServers returns" +
294                                   sb.toString() ) ;
295            }
296
297            return servers;
298        }
299    }
300
301    public int getServerID(String applicationName) throws ServerNotRegistered {
302        synchronized (db) {
303            int result = -1 ;
304
305            for (Enumeration serverIds = db.serverTable.keys();
306                 serverIds.hasMoreElements();)
307                {
308                    Integer nextServerId = (Integer) serverIds.nextElement();
309                    DBServerDef dbServerDef =
310                        (DBServerDef) db.serverTable.get(nextServerId);
311
312                    if (dbServerDef.applicationName.equals(applicationName)) {
313                        result = nextServerId.intValue();
314                        break ;
315                    }
316                }
317
318            if (debug)
319                System.out.println("RepositoryImpl: getServerID for " +
320                                   applicationName + " is " + result ) ;
321
322            if (result == -1) {
323                throw (new ServerNotRegistered());
324            } else {
325                return result ;
326            }
327        }
328    }
329
330    public String[] getApplicationNames() {
331        synchronized (db) {
332            Vector v = new Vector();
333            for (Enumeration serverIds = db.serverTable.keys();
334                 serverIds.hasMoreElements();)
335                {
336                    Integer nextServerId = (Integer) serverIds.nextElement();
337
338                    DBServerDef dbServerDef = (DBServerDef)db.serverTable.get(
339                                                                              nextServerId);
340
341                    if (!dbServerDef.applicationName.equals(""))
342                        v.addElement( dbServerDef.applicationName ) ;
343                }
344
345            String[] apps = new String[v.size()];
346            for (int i = 0; i < v.size(); i++) {
347                apps[i] = (String)v.elementAt(i);
348            }
349
350            if (debug) {
351                StringBuffer sb = new StringBuffer() ;
352                for (int ctr=0; ctr<apps.length; ctr++) {
353                    sb.append( ' ' ) ;
354                    sb.append( apps[ctr] ) ;
355                }
356
357                System.out.println( "RepositoryImpl: getApplicationNames returns " +
358                                    sb.toString() ) ;
359            }
360
361            return apps;
362        }
363    }
364    /**
365     * Typically the Repositoy is created within the ORBd VM but it can
366     * be independently started as well.
367     */
368    public static void main(String args[]) {
369        boolean debug = false ;
370        for (int ctr=0; ctr<args.length; ctr++)
371            if (args[ctr].equals("-debug"))
372                debug = true ;
373
374        try {
375            // See Bug 4396928 for more information about why we are
376            // initializing the ORBClass to PIORB (now ORBImpl, but see the bug).
377            Properties props = new Properties();
378            props.put("org.omg.CORBA.ORBClass",
379                "com.sun.corba.se.impl.orb.ORBImpl");
380            ORB orb = (ORB) ORB.init(args, props);
381
382            // create the repository object
383            String db = System.getProperty( ORBConstants.DB_PROPERTY,
384                    ORBConstants.DEFAULT_DB_NAME );
385            RepositoryImpl repository = new RepositoryImpl(orb, new File(db),
386                                                           debug);
387
388            // wait for shutdown
389            orb.run();
390        } catch (Exception ex) {
391            ex.printStackTrace();
392        }
393    }
394
395    transient private boolean debug = false;
396
397    final static int illegalServerId = -1;
398
399    transient private RepositoryDB db = null;
400
401    transient ORB orb = null;
402
403    transient ActivationSystemException wrapper ;
404
405    class RepositoryDB implements Serializable
406    {
407        File            db;
408        Hashtable       serverTable;
409        Integer         serverIdCounter;
410
411        RepositoryDB(File dbFile) {
412
413            db = dbFile;
414
415            // initialize the Server Id counter and hashtable.
416            // the lower id range is reserved for system servers
417            serverTable     = new Hashtable(255);
418            serverIdCounter = new Integer(256);
419        }
420
421        int incrementServerIdCounter()
422        {
423            int value = serverIdCounter.intValue();
424            serverIdCounter = new Integer(++value);
425
426            return value;
427        }
428
429        void flush()
430        {
431            try {
432                db.delete();
433                FileOutputStream fos = new FileOutputStream(db);
434                ObjectOutputStream oos = new ObjectOutputStream(fos);
435                oos.writeObject(this);
436                oos.flush();
437                oos.close();
438            } catch (Exception ex) {
439                throw wrapper.cannotWriteRepositoryDb( ex ) ;
440            }
441        }
442    }
443
444    class DBServerDef implements Serializable
445    {
446        public String toString() {
447            return "DBServerDef(applicationName=" + applicationName +
448                ", name=" + name +
449                ", classPath=" + classPath +
450                ", args=" + args +
451                ", vmArgs=" + vmArgs +
452                ", id=" + id +
453                ", isInstalled=" + isInstalled + ")" ;
454        }
455
456        DBServerDef(ServerDef server, int server_id) {
457            applicationName     = server.applicationName ;
458            name        = server.serverName;
459            classPath   = server.serverClassPath;
460            args        = server.serverArgs;
461            vmArgs      = server.serverVmArgs;
462            id          = server_id;
463            isInstalled = false ;
464        }
465
466        String applicationName;
467        String name;
468        String classPath;
469        String args;
470        String vmArgs;
471        boolean isInstalled ;
472        int    id;
473    }
474}
475