Index: src/test/java/org/glassfish/admin/rest/TokenAuthenticationTest.java =================================================================== --- src/test/java/org/glassfish/admin/rest/TokenAuthenticationTest.java (revision 47498) +++ src/test/java/org/glassfish/admin/rest/TokenAuthenticationTest.java (working copy) @@ -71,13 +71,14 @@ assertTrue(isSuccess(response)); //Delete the token - response = client.resource(getAddress(URL_DOMAIN_SESSIONS) + "/" + token).cookie(new Cookie(GF_REST_TOKEN_COOKIE_NAME, token)).delete(ClientResponse.class); delete(URL_DOMAIN_SESSIONS); + response = client.resource(getAddress(URL_DOMAIN_SESSIONS) + "/" + token).cookie(new Cookie(GF_REST_TOKEN_COOKIE_NAME, token)).delete(ClientResponse.class); + delete(URL_DOMAIN_SESSIONS); assertTrue(isSuccess(response)); } @Test public void testAuthRequired() { - Map newUser = new HashMap() {{ + Map newUser = new HashMap() {{ put("id", AUTH_USER_NAME); put("groups", TEST_GROUP); put("AS_ADMIN_USERPASSWORD", AUTH_PASSWORD); Property changes on: src/main/java/org/glassfish/admin/rest/adapter ___________________________________________________________________ Added: svn:ignore + .RestAdapter.java.swp Index: src/main/java/org/glassfish/admin/rest/adapter/RestAdapter.java =================================================================== --- src/main/java/org/glassfish/admin/rest/adapter/RestAdapter.java (revision 47498) +++ src/main/java/org/glassfish/admin/rest/adapter/RestAdapter.java (working copy) @@ -108,7 +108,7 @@ @Inject Events events; - + @Inject Habitat habitat; @@ -122,7 +122,10 @@ @Inject ServerEnvironment serverEnvironment; - + + @Inject + SessionManager sessionManager; + private volatile LazyJerseyInterface lazyJerseyInterface =null; @Inject @@ -152,7 +155,7 @@ @Override public void service(Request req, Response res) { LogHelper.getDefaultLogger().finer("Rest adapter !"); - LogHelper.getDefaultLogger().finer("Received resource request: " + req.getRequestURI()); + LogHelper.getDefaultLogger().log(Level.FINER, "Received resource request: {0}", req.getRequestURI()); try { res.setCharacterEncoding(Constants.ENCODING); @@ -260,7 +263,7 @@ // FIXME: Implement according to JavaDoc above... /* if (anonymousUser) { - String anonUser = + String anonUser = req.setAttribute("restUser", anonUser); return true; } @@ -268,7 +271,7 @@ return false; } - private boolean authenticateViaRestToken(Request req) { + private boolean authenticateViaRestToken(Request req) { boolean authenticated = false; Cookie[] cookies = req.getCookies(); String restToken = null; @@ -281,7 +284,7 @@ } if(restToken != null) { - authenticated = SessionManager.getSessionManager().authenticate(restToken, req); + authenticated = sessionManager.authenticate(restToken, req); } return authenticated; } @@ -399,7 +402,7 @@ return epd.getListenAddress(); } - + @Override public List getVirtualServers() { return epd.getAsadminHosts(); @@ -487,7 +490,7 @@ Set> classes = getResourcesConfig(); adapter = lazyJerseyInterface.exposeContext(classes, sc, habitat); // ((HttpHandler) adapter).setResourcesContextPath(context); - + logger.info("Listening to REST requests at context: " + context + "/domain"); } } Index: src/main/java/org/glassfish/admin/rest/RestConfig.java =================================================================== --- src/main/java/org/glassfish/admin/rest/RestConfig.java (revision 47498) +++ src/main/java/org/glassfish/admin/rest/RestConfig.java (working copy) @@ -51,16 +51,16 @@ * */ @Configured +public interface RestConfig extends ConfigExtension { -public interface RestConfig extends ConfigExtension { - public static String DEBUG = "debug"; public static String INDENTLEVEL ="indentLevel"; public static String SHOWHIDDENCOMMANDS ="showHiddenCommands"; public static String WADLGENERATION ="wadlGeneration"; public static String LOGRESPONSES ="logOutput"; public static String LOGINPUTS ="logInput"; - public static String SHOWDEPRECATEDITEMS ="showDeprecatedItems"; + public static String SHOWDEPRECATEDITEMS = "showDeprecatedItems"; + public static String SESSIONTOKENTIMEOUT = "sessionTokenTimeout"; @Attribute(defaultValue = "false", dataType = Boolean.class) public String getDebug(); @@ -91,9 +91,14 @@ public String getLogInput(); public void setLogInput(String logInput); - + @Attribute(defaultValue = "false", dataType = Boolean.class) public String getShowDeprecatedItems(); public void setShowDeprecatedItems(String showDeprecatedItems); + + @Attribute(defaultValue = "30", dataType = Integer.class) + public String getSessionTokenTimeout(); + + public void setSessionTokenTimeout(String timeout); } Property changes on: src/main/java/org/glassfish/admin/rest/generator ___________________________________________________________________ Added: svn:ignore + .CommandResourceMetaData.java.swp Index: src/main/java/org/glassfish/admin/rest/generator/CommandResourceMetaData.java =================================================================== --- src/main/java/org/glassfish/admin/rest/generator/CommandResourceMetaData.java (revision 47498) +++ src/main/java/org/glassfish/admin/rest/generator/CommandResourceMetaData.java (working copy) @@ -235,6 +235,7 @@ {"Domain", "_dump-hk2", "POST", "_dump-hk2", "_dump-hk2"}, {"Domain", "_get-habitat-info", "GET", "_get-habitat-info", "_get-habitat-info"}, {"Domain", "_get-log-file", "GET", "_get-log-file", "_get-log-file"}, + {"Domain", "_get-rest-admin-config", "GET", "_get-rest-admin-config", "_get-rest-admin-config"}, {"Domain", "_get-targets", "GET", "_get-targets", "_get-targets"}, {"Domain", "_gms-announce-after-start-cluster-command", "POST", "_gms-announce-after-start-cluster-command", "_gms-announce-after-start-cluster-command"}, {"Domain", "_gms-announce-after-stop-cluster-command", "POST", "_gms-announce-after-stop-cluster-command", "_gms-announce-after-stop-cluster-command"}, @@ -251,6 +252,7 @@ {"Domain", "_register-instance", "POST", "_register-instance", "_register-instance"}, {"Domain", "_register-instance-at-instance", "POST", "_register-instance-at-instance", "_register-instance-at-instance"}, {"Domain", "_restart-instance", "POST", "_restart-instance", "_restart-instance"}, + {"Domain", "_set-rest-admin-config", "POST", "_set-rest-admin-config", "_set-rest-admin-config"}, {"Domain", "_stop-instance", "POST", "_stop-instance", "_stop-instance"}, {"Domain", "_synchronize-files", "POST", "_synchronize-files", "_synchronize-files"}, {"Domain", "_unregister-instance", "POST", "_unregister-instance", "_unregister-instance"}, @@ -345,8 +347,6 @@ {"Protocol", "delete-protocol-filter", "DELETE", "delete-protocol-filter", "Delete", "protocol=$parent"}, {"Protocol", "delete-protocol-finder", "DELETE", "delete-protocol-finder", "Delete", "protocol=$parent"}, {"Protocol", "create-ssl", "POST", "create-ssl", "Create", "id=$parent", "type=http-listener"}, - // {"Config", "_get-rest-admin-config", "GET", "_get-rest-admin-config", "_get-rest-admin-config"}, - // {"Config", "_set-rest-admin-config", "POST", "_set-rest-admin-config", "_set-rest-admin-config"}, {"Resources", "_get-activation-spec-class", "GET", "get-activation-spec-class", "Get Activation Spec Class"}, {"Resources", "_get-admin-object-class-names", "GET", "get-admin-object-class-names", "Get Admin Object Class Names"}, {"Resources", "_get-admin-object-config-properties", "GET", "get-admin-object-config-properties", "Get Admin Object Config Properties"}, @@ -429,4 +429,4 @@ {"NetworkListener", "FindHttpProtocolResource", "find-http-protocol"}, {"Server", "SystemPropertiesCliResource", "system-properties"} }; -} \ No newline at end of file +} Index: src/main/java/org/glassfish/admin/rest/SessionManager.java =================================================================== --- src/main/java/org/glassfish/admin/rest/SessionManager.java (revision 47498) +++ src/main/java/org/glassfish/admin/rest/SessionManager.java (working copy) @@ -40,28 +40,37 @@ package org.glassfish.admin.rest; +import com.sun.enterprise.config.serverbeans.Config; +import com.sun.enterprise.config.serverbeans.Domain; import java.math.BigInteger; import java.security.SecureRandom; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import org.glassfish.grizzly.http.server.Request; +import org.jvnet.hk2.annotations.Inject; +import org.jvnet.hk2.annotations.Scoped; +import org.jvnet.hk2.annotations.Service; +import org.jvnet.hk2.component.Habitat; +import org.jvnet.hk2.component.Singleton; /** - * Manages Rest Sessions. + * Manages Rest Sessions. * @author Mitesh Meswani */ +@Service +@Scoped(Singleton.class) public class SessionManager { - - //TODO Singleton pattern. Get rid of it in next checkin. Put SessionManager at application level in ResourceConfig - private static SessionManager theSessionManager = new SessionManager(); - private SessionManager() {} - public static SessionManager getSessionManager() { return theSessionManager;} - + @Inject + private Habitat habitat; + private RestConfig restConfig = null; private final SecureRandom randomGenerator = new SecureRandom(); - private Map activeSessions = new ConcurrentHashMap(); //To guard against parallel mutation corrupting the map + // package/private to help minimize the chances of someone instantiating this directly + SessionManager() { + } + //TODO createSession is public. this package should not be exported public String createSession(Request req) { String sessionId; @@ -75,6 +84,7 @@ public boolean authenticate(String sessionId, Request req) { boolean authenticated = false; + purgeInactiveSessions(); if(sessionId != null) { SessionData sessionData = activeSessions.get(sessionId); @@ -113,27 +123,39 @@ private void purgeInactiveSessions() { Set> activeSessionsSet = activeSessions.entrySet(); for (Map.Entry entry : activeSessionsSet) { - if(!entry.getValue().isSessionActive() ) { + if (!entry.getValue().isSessionActive()) { activeSessionsSet.remove(entry); } } } + private RestConfig getRestConfig() { + if (restConfig == null) { + Domain domain = habitat.getComponent(Domain.class); + if (domain != null) { + Config config = domain.getConfigNamed("server-config"); + if (config != null) { + restConfig = config.getExtensionByType(RestConfig.class); + + } + } + } + return restConfig; + } + + private boolean isSessionExist(String sessionId) { return activeSessions.containsKey(sessionId); } - private static class SessionData{ - private static long INACTIVE_SESSION_DEFAULT_LIFETIME_IN_MILIS = 30 /*mins*/ * 60 /*secs/min*/ * 1000 /*milis/seconds*/; - private String sessionId; + private class SessionData{ /** IP address of client as obtained from Grizzly request */ private String clientAddress; - private long creationTime = System.currentTimeMillis(); - private long lassAccessedTime = creationTime; - private long inactiveSessionLifeTime = INACTIVE_SESSION_DEFAULT_LIFETIME_IN_MILIS; + private long lastAccessedTime = System.currentTimeMillis(); + private final String DISABLE_REMOTE_ADDRESS_VALIDATION_PROPERTY_NAME = "org.glassfish.admin.rest.disable.remote.address.validation"; + private final boolean disableRemoteAddressValidation = Boolean.getBoolean(DISABLE_REMOTE_ADDRESS_VALIDATION_PROPERTY_NAME); public SessionData(String sessionId, Request req) { - this.sessionId = sessionId; this.clientAddress = req.getRemoteAddr(); } @@ -141,19 +163,21 @@ * @return true if the session has not timed out. false otherwise */ public boolean isSessionActive() { - return lassAccessedTime + inactiveSessionLifeTime > System.currentTimeMillis(); + long inactiveSessionLifeTime = 30 /*mins*/ * 60 /*secs/min*/ * 1000 /*milis/seconds*/; + RestConfig restConfig = getRestConfig(); + if (restConfig != null) { + inactiveSessionLifeTime = Integer.parseInt(restConfig.getSessionTokenTimeout()) * 60000; // minutes * 60 seconds * 1000 millis + } + return lastAccessedTime + inactiveSessionLifeTime > System.currentTimeMillis(); } /** * Update the last accessed time to current time */ public void updateLastAccessTime() { - lassAccessedTime = System.currentTimeMillis(); + lastAccessedTime = System.currentTimeMillis(); } - private static final String DISABLE_REMOTE_ADDRESS_VALIDATION_PROPERTY_NAME = "org.glassfish.admin.rest.disable.remote.address.validation"; - private static final boolean disableRemoteAddressValidation = Boolean.getBoolean(DISABLE_REMOTE_ADDRESS_VALIDATION_PROPERTY_NAME); - /** * @return true if session is still active and the request is from same remote address as the one session was * initiated from Index: src/main/java/org/glassfish/admin/rest/LazyJerseyInit.java =================================================================== --- src/main/java/org/glassfish/admin/rest/LazyJerseyInit.java (revision 47498) +++ src/main/java/org/glassfish/admin/rest/LazyJerseyInit.java (working copy) @@ -134,6 +134,7 @@ rc.getSingletons().add(new SingletonTypeInjectableProvider(ServerContext.class, sc) {}); rc.getSingletons().add(new SingletonTypeInjectableProvider(Habitat.class, habitat) {}); rc.getSingletons().add(new SingletonTypeInjectableProvider(Client.class, Client.create()) {}); + rc.getSingletons().add(new SingletonTypeInjectableProvider(SessionManager.class, habitat.getComponent(SessionManager.class)) {}); //Use common classloader. Jersey artifacts are not visible through //module classloader Property changes on: src/main/java/org/glassfish/admin/rest/cli ___________________________________________________________________ Added: svn:ignore + .SetRestConfig.java.swp Index: src/main/java/org/glassfish/admin/rest/cli/SetRestConfig.java =================================================================== --- src/main/java/org/glassfish/admin/rest/cli/SetRestConfig.java (revision 47498) +++ src/main/java/org/glassfish/admin/rest/cli/SetRestConfig.java (working copy) @@ -91,6 +91,8 @@ private String logOutput; @Param(optional = true) private String logInput; + @Param(optional = true) + private String sessionTokenTimeout; @Override public void execute(AdminCommandContext context) { @@ -164,6 +166,9 @@ if (logInput != null) { param.setLogInput(logInput); } + if (sessionTokenTimeout != null) { + param.setSessionTokenTimeout(sessionTokenTimeout); + } Index: src/main/java/org/glassfish/admin/rest/cli/GetRestConfig.java =================================================================== --- src/main/java/org/glassfish/admin/rest/cli/GetRestConfig.java (revision 47498) +++ src/main/java/org/glassfish/admin/rest/cli/GetRestConfig.java (working copy) @@ -57,11 +57,11 @@ /** * Remote asadmin command: get-rest-config - * + * * Purpose: Allows the invoker to get values for the REST module. - * - * * + * + * * @author Ludovic Champenois * */ @@ -72,6 +72,7 @@ @Inject(name = ServerEnvironment.DEFAULT_INSTANCE_NAME) Config config; + @Inject private Habitat habitat; @@ -84,7 +85,7 @@ if (restConfig == null) { - report.setMessage("debug=false, indentLevel=-1, showHiddenCommands=false, wadlGeneration=false, logOutput=false, logInput=false, showDeprecatedItems=false"); + report.setMessage("debug=false, indentLevel=-1, showHiddenCommands=false, wadlGeneration=false, logOutput=false, logInput=false, showDeprecatedItems=false, sessionTokenTimeout=30"); report.getTopMessagePart().addProperty("debug", "false"); report.getTopMessagePart().addProperty("indentLevel", "-1"); @@ -93,10 +94,11 @@ report.getTopMessagePart().addProperty("wadlGeneration", "" + "false"); report.getTopMessagePart().addProperty("logOutput", "" + "false"); report.getTopMessagePart().addProperty("logInput", "" + "false"); + report.getTopMessagePart().addProperty("sessionTokenTimeout", "30"); } else { report.setMessage("debug="+restConfig.getDebug()+", indentLevel="+restConfig.getIndentLevel()+", showHiddenCommands="+restConfig.getShowHiddenCommands()+", wadlGeneration="+restConfig.getWadlGeneration()+", logOutput="+restConfig.getLogOutput() - +", logInput="+restConfig.getLogInput()); + +", logInput="+restConfig.getLogInput() + ", sessionTokenTimeout="+restConfig.getSessionTokenTimeout()); report.getTopMessagePart().addProperty("debug", restConfig.getDebug()); report.getTopMessagePart().addProperty("indentLevel", restConfig.getIndentLevel()); @@ -105,6 +107,7 @@ report.getTopMessagePart().addProperty("wadlGeneration", restConfig.getWadlGeneration()); report.getTopMessagePart().addProperty("logOutput", restConfig.getLogOutput()); report.getTopMessagePart().addProperty("logInput", restConfig.getLogInput()); + report.getTopMessagePart().addProperty("sessionTokenTimeout", "" + restConfig.getSessionTokenTimeout()); } Index: src/main/java/org/glassfish/admin/rest/resources/SessionsResource.java =================================================================== --- src/main/java/org/glassfish/admin/rest/resources/SessionsResource.java (revision 47498) +++ src/main/java/org/glassfish/admin/rest/resources/SessionsResource.java (working copy) @@ -62,7 +62,8 @@ */ @Path("/sessions") public class SessionsResource { - SessionManager sessionManager = SessionManager.getSessionManager(); //TODO move this to look up from injected app properties + @Context + SessionManager sessionManager; @Context protected HttpHeaders requestHeaders; @@ -97,7 +98,7 @@ @Path("{sessionId}/") public SessionResource getSessionResource(@PathParam("sessionId")String sessionId) { - return new SessionResource(sessionId, requestHeaders, uriInfo); + return new SessionResource(sessionManager, sessionId, requestHeaders, uriInfo); } } Index: src/main/java/org/glassfish/admin/rest/resources/SessionResource.java =================================================================== --- src/main/java/org/glassfish/admin/rest/resources/SessionResource.java (revision 47498) +++ src/main/java/org/glassfish/admin/rest/resources/SessionResource.java (working copy) @@ -61,9 +61,10 @@ private HttpHeaders requestHeaders; private UriInfo uriInfo; - SessionManager sessionManager = SessionManager.getSessionManager(); + SessionManager sessionManager; - public SessionResource(String sessionId, HttpHeaders requestHeaders, UriInfo uriInfo) { + public SessionResource(SessionManager sessionManager, String sessionId, HttpHeaders requestHeaders, UriInfo uriInfo) { + this.sessionManager = sessionManager; this.sessionId = sessionId; this.requestHeaders = requestHeaders; this.uriInfo = uriInfo;