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 446 bojilova
        if ( username.equals("public") ) {
191
          out.append("</" + tag + ">");
192
          return out.toString();
193
        }
194 411 bojilova
        String groupname = (String)this.session.getAttribute("groupname");
195
        out.append("  " + groupname + "\n");
196
197
        Stack usersGroups = new Stack();
198
        usersGroups = (Stack)this.session.getAttribute("usersgroups");
199
        String val = "";
200
        StringBuffer res = new StringBuffer();
201
        while ( !usersGroups.empty() ) {
202
          val = "    " + (String)usersGroups.pop() + "\n" + val;
203
          if ( val.startsWith("    <groupname>") ) {
204
            val = "  <group>\n" + val + "  </group>\n";
205
            res.insert(0, val);
206
            val = "";
207
          }
208
        }
209
        out.append(res.toString());
210
      }
211
      out.append("</" + tag + ">");
212
213
      return out.toString();
214
215
    }
216
217
    /** Try to make user authentication through SRB RMI Connection
218
      * Using that connection to get:
219
      *  . the groupname of connected user;
220
      *  . a whole list of all groups and users in MCAT.
221
      */
222
    private boolean userAuth(String username, String password)
223 209 bojilova
                    throws RemoteException  {
224 411 bojilova
//      synchronized(this) {
225
        int srbconn = 0;
226 294 bojilova
227 411 bojilova
        // look up for SRBJavaGlue
228
        try {
229
          String name = "//" + RMIhost + "/SrbJavaGlue";
230
          srbJG = (SrbJavaGlueInterface)Naming.lookup(name);
231
        } catch (Exception e) {
232
          try {
233
            rmicon.restart();
234
          } catch (Exception rmie) {}
235
          // The SRB server is not running or it is busy now
236
          throw new
237 294 bojilova
            RemoteException("MetaCatSession look up for SrbJavaGlue failed");
238 411 bojilova
        }
239
240
        // try SRB RMI Connection
241
        // integer value of the SBR Connection ID is returned only
242
        try {
243
          srbconn = srbJG.rmiConnectJ( srbHost, srbPort, password, username );
244
        } catch (RemoteException e) {
245
          try {
246
            rmicon.restart();
247
          } catch (Exception rmie) {}
248
          throw new RemoteException("MetaCatSession.userAuth() - " +
249
                                  "Error on rmiConnectJ(): " + e.getMessage());
250
        }
251 209 bojilova
252 411 bojilova
        // check if successfull
253
        if ( srbconn == 0 ) {
254
          throw new RemoteException("The SRB Server is not running or it is busy now");
255
        } else if ( srbconn < 0 ) {
256
          try {
257
            rmicon.restart();
258
          } catch (Exception rmie) {}
259
          return false;
260
        }
261 209 bojilova
262 411 bojilova
        // get the Group name of connected user;
263
        String groupname = null;
264
        try {
265
          groupname = getGroupname(srbconn, username);
266
          this.session.setAttribute("groupname", groupname);
267
        } catch (RemoteException e) {
268
          throw new RemoteException("MetaCatSession.userAuth() - " +
269
                    "Error on getGroupname(): " + e.getMessage());
270
        }
271
        // get all users and groups from MCAT
272
        Stack usersGroupsList = new Stack();
273
        try {
274
          usersGroupsList = getUsersGroups(srbconn);
275
          this.session.setAttribute("usersgroups", usersGroupsList);
276
        } catch (RemoteException e) {
277
          throw new RemoteException("MetaCatSession.userAuth() - " +
278
                    "Error on getUsersGroups(): " + e.getMessage());
279
        }
280
281 209 bojilova
282 411 bojilova
        // we don't need that connection. close it.
283
        try {
284
          int err = srbJG.rmiFinishJ( srbconn );
285
        } catch (RemoteException e) {}
286 209 bojilova
287 411 bojilova
        // store SRB Connection in the session for later use if necessary
288
        this.session.setAttribute("srbconnection", new Integer(srbconn));
289
290
//        try {
291
//            wait(5000);
292
//        } catch (Exception e) {}
293
//        try {
294
//            notifyAll();
295
//        } catch (Exception e) {}
296
        return true;
297
298
//      } // end of synchronized(this)
299 209 bojilova
    }
300 234 bojilova
301 411 bojilova
    // get the Groupname of connected user
302
    private String getGroupname (int conn, String username)
303
                throws RemoteException
304
    {
305
306
	    String[] qval;
307
	    int[] qvalInx;
308
	    int[] selVal;
309
310
	    qval = new String [3];
311
	    qval[0] = new String (" not like  '%$deleted%'");
312
	    qval[1] = new String (" = '" + username + "'");
313
	    qval[2] = new String (" <> 'public'");
314
315
	    qvalInx = new int[3];
316
	    qvalInx[0] = USER_NAME;
317
	    qvalInx[1] = USER_NAME;
318
	    qvalInx[2] = USER_GROUP_NAME;
319
320
	    selVal = new int[2];
321
      selVal[0] = USER_GROUP_NAME;
322
      selVal[1] = USER_NAME;
323
324
	    // generate a query and get the resultset
325
	    Stack selRes = new Stack();
326
	    selRes = getGenQueResult (conn, qval, qvalInx, selVal);
327
	    String dummy = (String)selRes.pop();
328
      return (String)selRes.pop();
329
    }
330
331
    // get all users and groups from MCAT
332
    private Stack getUsersGroups (int conn)
333
                throws RemoteException
334
    {
335
336
	    String[] qval;
337
	    int[] qvalInx;
338
	    int[] selVal;
339
340
	    qval = new String [1];
341
	    qval[0] = new String (" not like  '%$deleted%'");
342
	    //qval[1] = new String (" <> 'public'");
343
344
	    qvalInx = new int[1];
345
	    qvalInx[0] = USER_NAME;
346
	    //qvalInx[1] = USER_GROUP_NAME;
347
348
	    selVal = new int[2];
349
      selVal[0] = USER_GROUP_NAME;
350
      selVal[1] = USER_NAME;
351
352
	    // generate a query and get the resultset
353
	    Stack selRes = new Stack();
354
	    selRes = getGenQueResult (conn, qval, qvalInx, selVal);
355
      return selRes;
356
    }
357
358
    // try to generate query and run and retrieve all rows
359
    private Stack getGenQueResult(int conn, String[] qval,
360
                                int qvalInx[], int selVal[])
361
                throws RemoteException
362
    {
363
364
        int queResultCount = 0;
365
        int queResultIndex = 0;
366
        int selLen = selVal.length;
367
        String[] queResult = new String[selLen];
368
        Stack resultset = new Stack();
369
        String currGroupname = null;
370
371
        // get first row
372
        try {
373
          queResultCount = srbJG.srbGenQuery( conn, 0, qval, qvalInx, selVal);
374
          for (int i = 0; i < selLen; i++) {
375
            queResult[i] = srbJG.getGenQueResultJ(i, queResultIndex);
376
          }
377
          resultset.push("<groupname>" + queResult[0] + "</groupname>");
378
          resultset.push("<username>" + queResult[1] + "</username>");
379
          currGroupname = queResult[0];
380
          queResultIndex++;
381
382
          // get next rows
383
          while (queResult != null) {
384
            if ( queResultIndex >= queResultCount ) {
385
                queResultIndex = 0;
386
                queResultCount = srbJG.getMoreGenQueRowsJ( conn, 0);
387
                if (queResultCount <= 0) {
388
                  return resultset;
389
                }
390
            }
391
392
            for (int i = 0; i < selLen; i++) {
393
                queResult[i] = srbJG.getGenQueResultJ(i, queResultIndex);
394
            }
395
            if ( !currGroupname.equals(queResult[0]) ) {
396
              resultset.push("<groupname>" + queResult[0] + "</groupname>");
397
              currGroupname = queResult[0];
398
            }
399
            resultset.push("<username>" + queResult[1] + "</username>");
400
            queResultIndex++;
401
          }
402
        } catch (RemoteException e) {
403
          throw new RemoteException(e.getMessage());
404
        }
405
406
        return resultset;
407
    }
408
409
410 209 bojilova
    /**
411
     * Invalidate this HTTPSession object.
412
     * All objects stored in the session are unbound
413
     */
414 411 bojilova
    private void disconnect() {
415 209 bojilova
416
        this.session.invalidate();
417
    }
418
419 411 bojilova
}