Project

General

Profile

1 209 bojilova
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that tracks sessions for MetaCatServlet users.
4
 *  Copyright: 2000 Regents of the University of California and the
5
 *             National Center for Ecological Analysis and Synthesis
6
 *    Authors: Matt Jones
7 349 jones
 *    Release: @release@
8 209 bojilova
 *
9
 *   '$Author$'
10
 *     '$Date$'
11
 * '$Revision$'
12
 */
13
14
package edu.ucsb.nceas.metacat;
15
16
import javax.servlet.http.HttpSession;
17
import javax.servlet.http.HttpServletRequest;
18 411 bojilova
import javax.servlet.http.HttpServletResponse;
19 209 bojilova
import java.util.Properties;
20 237 bojilova
import java.util.PropertyResourceBundle;
21 411 bojilova
import java.util.Stack;
22 209 bojilova
import java.io.FileInputStream;
23 294 bojilova
import java.io.PrintWriter;
24 209 bojilova
import java.rmi.*;
25
import SrbJavaGlueInterface;
26 294 bojilova
import RMIControllerInterface;
27 209 bojilova
28
/**
29
 * A Class that implements session tracking for MetaCatServlet users.
30
 * User's login data are stored in the session object.
31
 * User authentication is made through SRB RMI Connection.
32
 */
33
public class MetaCatSession {
34
35 294 bojilova
    static String debug = null;
36 209 bojilova
    HttpSession session = null;
37 411 bojilova
38
    // DCS-ATTRIBUTE-INDEX
39
    // They are from mdasC_db2_externs.h.
40
    final static int USER_NAME = 7;
41
    final static int USER_GROUP_NAME = 3;
42
43 209 bojilova
    // JNI (Java Native Interface) routines for SRB
44
    static String srbHost;
45
    static String srbPort;
46 294 bojilova
    static String RMIhost;
47
    static RMIControllerInterface rmicon;
48 234 bojilova
    static SrbJavaGlueInterface srbJG;
49 209 bojilova
    static {
50 294 bojilova
        try {
51 237 bojilova
            PropertyResourceBundle SRBProps = null;
52 209 bojilova
            // SRB properties that tells about the location of SRB RMI Server
53
            // srbProps.properties should reside on metacat server
54 237 bojilova
            SRBProps = (PropertyResourceBundle)
55 252 bojilova
                        PropertyResourceBundle.getBundle("edu.ucsb.nceas.metacat.srbProps");
56 237 bojilova
            srbHost = (String)SRBProps.handleGetObject("host");
57
            srbPort = (String)SRBProps.handleGetObject("port");
58 209 bojilova
            // should handle missing RMIhost name here
59 294 bojilova
            RMIhost = (String)SRBProps.handleGetObject("RMIhost");
60
            String name = "//" + RMIhost + "/RMIController";
61
            rmicon = (RMIControllerInterface)Naming.lookup(name);
62
            name = "//" + RMIhost + "/SrbJavaGlue";
63 209 bojilova
            srbJG = (SrbJavaGlueInterface)Naming.lookup(name);
64
        } catch (Exception e) {
65 294 bojilova
            System.err.println("MetaCatSession static: " + e.getMessage());
66
            System.exit(0);
67 209 bojilova
        }
68
    }
69
70
    /** Construct a MetaCatSession
71
     *
72
     * @param request the request made from the client
73
     * @param username the username entered when login
74
     * @param password the password entered when login
75
     */
76
    public MetaCatSession (HttpServletRequest request,
77 294 bojilova
                            String username, String password)
78
                            throws IllegalStateException {
79 209 bojilova
      // create a new HTTPSession object
80
      this.session = getSession(request, username, password);
81
    }
82
83
    /** Get new HttpSession and store username & password in it */
84
    private HttpSession getSession(HttpServletRequest request,
85 229 bojilova
                            String username, String password)
86
                            throws IllegalStateException {
87 333 bojilova
88 209 bojilova
      // get the current session object, create one if necessary
89
      HttpSession sess = request.getSession(true);
90
      // if it is still in use unvalidate and get a new one
91
      if ( !sess.isNew() ) {
92
        sess.invalidate();
93
        sess = request.getSession(true);
94
      }
95
      // store username & password in the session for later use if necessary
96 333 bojilova
      sess.setMaxInactiveInterval(-1);
97 337 bojilova
      sess.setAttribute("username", username);
98
      sess.setAttribute("password", password);
99 209 bojilova
100
      return sess;
101
    }
102
103 411 bojilova
    /** handle Login action for MetaCatServlet
104
      */
105
    public String userLogin(HttpServletResponse response,
106
                            String username, String password,
107
                            String action, String htmlpath) {
108
109
      String out = null;
110
111
      // for public connection only
112
      // this does not go through auth checking in SRB
113
      // the final implementation will need auth checking in SRB for public
114
      if ( username.equals("public") ) {
115
        try {
116
          if (action.equals("Login Client")) {
117
            String message = "User Authentication successful";
118
            out = formatOutput("success", message);
119
            return out;
120
          } else {
121
            response.sendRedirect(
122
                     response.encodeRedirectUrl(htmlpath + "/index.html"));
123
          }
124
        } catch ( java.io.IOException ioe) {
125
          disconnect();
126
          String message = "MetaCatSession.userLogin() - " +
127
                      "Error on redirect of HttpServletResponse: " +
128
                      ioe.getMessage();
129
          out = formatOutput("error", message);
130
          return out;
131
        }
132
      }
133
134
      // Auth checking in SRB.
135
      // It fails if not registered user provided.
136
      // It gets all users/groups from MCAT for implementing ACL for MetaCat
137
      // The last one probably will need to be done on separate MetaCatServlet
138
      // action instead on Login action
139
      try {
140
        if ( userAuth(username, password) ) {
141
          try {
142
            if (action.equals("Login Client")) {
143
144
              String message = "User Authentication successful";
145
              out = formatOutput("success", message);
146
147
            } else {
148
              response.sendRedirect(
149
                       response.encodeRedirectUrl(htmlpath + "/metacat.html"));
150
            }
151
          } catch ( java.io.IOException ioe) {
152
            disconnect();
153
            String message = "MetaCatSession.userLogin() - " +
154
                       "Error on redirect of HttpServletResponse: " +
155
                       ioe.getMessage();
156
            out = formatOutput("error", message);
157
          }
158
        // the user has not been authenticated by SRB
159
        } else {
160
            disconnect();
161
            String message = "SRB Connection failed. " +
162
                       "SRB RMI Server is not running now or " +
163
                       "user " + username +
164
                       " has not been authenticated to use the system.";
165
            out = formatOutput("error", message);
166
        }
167
      } catch ( java.rmi.RemoteException re) {
168
        disconnect();
169
        String message = "SRB Connection failed. " + re.getMessage();
170
        out = formatOutput("error", message);
171
      }
172
173
      return out;
174
    }
175
176
    /* format the output in xml for processing from client appl
177
     */
178
    private String formatOutput(String tag, String message) {
179
180
      StringBuffer out = new StringBuffer();
181
182
      out.append("<?xml version=\"1.0\"?>\n");
183
      out.append("<" + tag + ">");
184
      if ( tag.equals("error") ) {
185
        out.append(message);
186
      } else {
187
        out.append("\n  <message>" + message + "</message>\n");
188
        String username = (String)this.session.getAttribute("username");
189
        out.append("  <username>" + username + "</username>\n");
190
        String groupname = (String)this.session.getAttribute("groupname");
191
        out.append("  " + groupname + "\n");
192
193
        Stack usersGroups = new Stack();
194
        usersGroups = (Stack)this.session.getAttribute("usersgroups");
195
        String val = "";
196
        StringBuffer res = new StringBuffer();
197
        while ( !usersGroups.empty() ) {
198
          val = "    " + (String)usersGroups.pop() + "\n" + val;
199
          if ( val.startsWith("    <groupname>") ) {
200
            val = "  <group>\n" + val + "  </group>\n";
201
            res.insert(0, val);
202
            val = "";
203
          }
204
        }
205
        out.append(res.toString());
206
      }
207
      out.append("</" + tag + ">");
208
209
      return out.toString();
210
211
    }
212
213
    /** Try to make user authentication through SRB RMI Connection
214
      * Using that connection to get:
215
      *  . the groupname of connected user;
216
      *  . a whole list of all groups and users in MCAT.
217
      */
218
    private boolean userAuth(String username, String password)
219 209 bojilova
                    throws RemoteException  {
220 411 bojilova
//      synchronized(this) {
221
        int srbconn = 0;
222 294 bojilova
223 411 bojilova
        // look up for SRBJavaGlue
224
        try {
225
          String name = "//" + RMIhost + "/SrbJavaGlue";
226
          srbJG = (SrbJavaGlueInterface)Naming.lookup(name);
227
        } catch (Exception e) {
228
          try {
229
            rmicon.restart();
230
          } catch (Exception rmie) {}
231
          // The SRB server is not running or it is busy now
232
          throw new
233 294 bojilova
            RemoteException("MetaCatSession look up for SrbJavaGlue failed");
234 411 bojilova
        }
235
236
        // try SRB RMI Connection
237
        // integer value of the SBR Connection ID is returned only
238
        try {
239
          srbconn = srbJG.rmiConnectJ( srbHost, srbPort, password, username );
240
        } catch (RemoteException e) {
241
          try {
242
            rmicon.restart();
243
          } catch (Exception rmie) {}
244
          throw new RemoteException("MetaCatSession.userAuth() - " +
245
                                  "Error on rmiConnectJ(): " + e.getMessage());
246
        }
247 209 bojilova
248 411 bojilova
        // check if successfull
249
        if ( srbconn == 0 ) {
250
          throw new RemoteException("The SRB Server is not running or it is busy now");
251
        } else if ( srbconn < 0 ) {
252
          try {
253
            rmicon.restart();
254
          } catch (Exception rmie) {}
255
          return false;
256
        }
257 209 bojilova
258 411 bojilova
        // get the Group name of connected user;
259
        String groupname = null;
260
        try {
261
          groupname = getGroupname(srbconn, username);
262
          this.session.setAttribute("groupname", groupname);
263
        } catch (RemoteException e) {
264
          throw new RemoteException("MetaCatSession.userAuth() - " +
265
                    "Error on getGroupname(): " + e.getMessage());
266
        }
267
        // get all users and groups from MCAT
268
        Stack usersGroupsList = new Stack();
269
        try {
270
          usersGroupsList = getUsersGroups(srbconn);
271
          this.session.setAttribute("usersgroups", usersGroupsList);
272
        } catch (RemoteException e) {
273
          throw new RemoteException("MetaCatSession.userAuth() - " +
274
                    "Error on getUsersGroups(): " + e.getMessage());
275
        }
276
277 209 bojilova
278 411 bojilova
        // we don't need that connection. close it.
279
        try {
280
          int err = srbJG.rmiFinishJ( srbconn );
281
        } catch (RemoteException e) {}
282 209 bojilova
283 411 bojilova
        // store SRB Connection in the session for later use if necessary
284
        this.session.setAttribute("srbconnection", new Integer(srbconn));
285
286
//        try {
287
//            wait(5000);
288
//        } catch (Exception e) {}
289
//        try {
290
//            notifyAll();
291
//        } catch (Exception e) {}
292
        return true;
293
294
//      } // end of synchronized(this)
295 209 bojilova
    }
296 234 bojilova
297 411 bojilova
    // get the Groupname of connected user
298
    private String getGroupname (int conn, String username)
299
                throws RemoteException
300
    {
301
302
	    String[] qval;
303
	    int[] qvalInx;
304
	    int[] selVal;
305
306
	    qval = new String [3];
307
	    qval[0] = new String (" not like  '%$deleted%'");
308
	    qval[1] = new String (" = '" + username + "'");
309
	    qval[2] = new String (" <> 'public'");
310
311
	    qvalInx = new int[3];
312
	    qvalInx[0] = USER_NAME;
313
	    qvalInx[1] = USER_NAME;
314
	    qvalInx[2] = USER_GROUP_NAME;
315
316
	    selVal = new int[2];
317
      selVal[0] = USER_GROUP_NAME;
318
      selVal[1] = USER_NAME;
319
320
	    // generate a query and get the resultset
321
	    Stack selRes = new Stack();
322
	    selRes = getGenQueResult (conn, qval, qvalInx, selVal);
323
	    String dummy = (String)selRes.pop();
324
      return (String)selRes.pop();
325
    }
326
327
    // get all users and groups from MCAT
328
    private Stack getUsersGroups (int conn)
329
                throws RemoteException
330
    {
331
332
	    String[] qval;
333
	    int[] qvalInx;
334
	    int[] selVal;
335
336
	    qval = new String [1];
337
	    qval[0] = new String (" not like  '%$deleted%'");
338
	    //qval[1] = new String (" <> 'public'");
339
340
	    qvalInx = new int[1];
341
	    qvalInx[0] = USER_NAME;
342
	    //qvalInx[1] = USER_GROUP_NAME;
343
344
	    selVal = new int[2];
345
      selVal[0] = USER_GROUP_NAME;
346
      selVal[1] = USER_NAME;
347
348
	    // generate a query and get the resultset
349
	    Stack selRes = new Stack();
350
	    selRes = getGenQueResult (conn, qval, qvalInx, selVal);
351
      return selRes;
352
    }
353
354
    // try to generate query and run and retrieve all rows
355
    private Stack getGenQueResult(int conn, String[] qval,
356
                                int qvalInx[], int selVal[])
357
                throws RemoteException
358
    {
359
360
        int queResultCount = 0;
361
        int queResultIndex = 0;
362
        int selLen = selVal.length;
363
        String[] queResult = new String[selLen];
364
        Stack resultset = new Stack();
365
        String currGroupname = null;
366
367
        // get first row
368
        try {
369
          queResultCount = srbJG.srbGenQuery( conn, 0, qval, qvalInx, selVal);
370
          for (int i = 0; i < selLen; i++) {
371
            queResult[i] = srbJG.getGenQueResultJ(i, queResultIndex);
372
          }
373
          resultset.push("<groupname>" + queResult[0] + "</groupname>");
374
          resultset.push("<username>" + queResult[1] + "</username>");
375
          currGroupname = queResult[0];
376
          queResultIndex++;
377
378
          // get next rows
379
          while (queResult != null) {
380
            if ( queResultIndex >= queResultCount ) {
381
                queResultIndex = 0;
382
                queResultCount = srbJG.getMoreGenQueRowsJ( conn, 0);
383
                if (queResultCount <= 0) {
384
                  return resultset;
385
                }
386
            }
387
388
            for (int i = 0; i < selLen; i++) {
389
                queResult[i] = srbJG.getGenQueResultJ(i, queResultIndex);
390
            }
391
            if ( !currGroupname.equals(queResult[0]) ) {
392
              resultset.push("<groupname>" + queResult[0] + "</groupname>");
393
              currGroupname = queResult[0];
394
            }
395
            resultset.push("<username>" + queResult[1] + "</username>");
396
            queResultIndex++;
397
          }
398
        } catch (RemoteException e) {
399
          throw new RemoteException(e.getMessage());
400
        }
401
402
        return resultset;
403
    }
404
405
406 209 bojilova
    /**
407
     * Invalidate this HTTPSession object.
408
     * All objects stored in the session are unbound
409
     */
410 411 bojilova
    private void disconnect() {
411 209 bojilova
412
        this.session.invalidate();
413
    }
414
415 411 bojilova
}