Repository: flex-blazeds Updated Branches: refs/heads/develop f9201bc22 -> fdbf19e48
http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/fdbf19e4/opt/tomcat/tomcat-base/src/main/java/flex/messaging/security/TomcatLoginHolder.java ---------------------------------------------------------------------- diff --git a/opt/tomcat/tomcat-base/src/main/java/flex/messaging/security/TomcatLoginHolder.java b/opt/tomcat/tomcat-base/src/main/java/flex/messaging/security/TomcatLoginHolder.java new file mode 100755 index 0000000..d3a0449 --- /dev/null +++ b/opt/tomcat/tomcat-base/src/main/java/flex/messaging/security/TomcatLoginHolder.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package flex.messaging.security; + +/** + * Contains the last good TomcatLogin for use by the TomcatLoginCommand. + */ +public class TomcatLoginHolder +{ + private static ThreadLocal logins = new ThreadLocal(); + + // We should really make this one as a singleton instead of resetting it every time we call setLogin() + private static TomcatLogin nioBasedLogin; + + private TomcatLoginHolder() + { + // No-op. + } + + /** + * Saves the last valid login. + * + * @param login last valid login + */ + public static void setLogin(TomcatLogin login) + { + logins.set(login); + } + + /** + * Retrieves the last valid login. + * + * @return last valid login. + */ + public static TomcatLogin getLogin() + { + return logins.get() != null? (TomcatLogin)logins.get() : nioBasedLogin; + } + + /** + * Saves the nio based login. + * + * @param login the valid login that nio based endpoints should use + */ + public static void setNioBasedLogin(TomcatLogin login) + { + nioBasedLogin = login; + } +} http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/fdbf19e4/opt/weblogic/pom.xml ---------------------------------------------------------------------- diff --git a/opt/weblogic/pom.xml b/opt/weblogic/pom.xml new file mode 100644 index 0000000..31e679b --- /dev/null +++ b/opt/weblogic/pom.xml @@ -0,0 +1,61 @@ +<!-- + +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.flex.blazeds</groupId> + <artifactId>flex-messaging-opt</artifactId> + <version>4.7.0-SNAPSHOT</version> + </parent> + + <artifactId>flex-messaging-opt-weblogic</artifactId> + + <distributionManagement> + <site> + <id>blazeds_mvn_site</id> + <url>${maven.site.local.url}/flex-messaging-opt/${project.artifactId}</url> + </site> + </distributionManagement> + + <dependencies> + <dependency> + <groupId>com.weblogic</groupId> + <artifactId>wsexception</artifactId> + <version>7.0.5.0</version> + <scope>system</scope> + <systemPath>${basedir}/../../lib/wsexception.jar</systemPath> + </dependency> + <dependency> + <groupId>com.weblogic</groupId> + <artifactId>weblogic</artifactId> + <version>7.0.5.0</version> + <scope>system</scope> + <systemPath>${basedir}/../../lib/weblogic.jar</systemPath> + </dependency> + </dependencies> + + <properties> + <appserver>weblogic</appserver> + <source.dir>src/weblogic</source.dir> + <exclude.pattern>none</exclude.pattern> + </properties> + +</project> http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/fdbf19e4/opt/weblogic/src/main/java/flex/messaging/security/WeblogicLoginCommand.java ---------------------------------------------------------------------- diff --git a/opt/weblogic/src/main/java/flex/messaging/security/WeblogicLoginCommand.java b/opt/weblogic/src/main/java/flex/messaging/security/WeblogicLoginCommand.java new file mode 100755 index 0000000..0f698c8 --- /dev/null +++ b/opt/weblogic/src/main/java/flex/messaging/security/WeblogicLoginCommand.java @@ -0,0 +1,239 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package flex.messaging.security; + +import java.security.Principal; +import java.util.Iterator; +import java.util.List; + +import javax.security.auth.Subject; +import javax.security.auth.login.LoginException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import weblogic.security.SimpleCallbackHandler; +import weblogic.security.SubjectUtils; +import weblogic.security.services.Authentication; +import weblogic.servlet.security.ServletAuthentication; +import weblogic.security.Security; +import flex.messaging.FlexContext; + +/** + * Authenticates against WebLogic and if using an HttpServlet will store + * the authenticated user in the request. + */ +public class WeblogicLoginCommand extends AppServerLoginCommand implements PrincipalConverter +{ + /** {@inheritDoc} */ + public Principal doAuthentication(String username, Object credentials) + { + Principal principal = null; + + String password = extractPassword(credentials); + + if (password != null) + { + // Test for the presence of a response here (rather than request) because NIO + // endpoints require the alternate code path and they don't populate the response + // in FlexContext. + HttpServletResponse response = FlexContext.getHttpResponse(); + if (response != null) + { + HttpServletRequest request = FlexContext.getHttpRequest(); + int result = ServletAuthentication.FAILED_AUTHENTICATION; + try + { + result = ServletAuthentication.login(username, password, + request); + } + catch (LoginException e) + { + } + catch (NoSuchMethodError noSuchMethodError) + { + //even though we're not supporting WebLogic 7 anymore... + // Weblogic 7.0.4 didn't have login(), so try weak(). + result = ServletAuthentication.weak(username, password, + request); + } + + if (result != ServletAuthentication.FAILED_AUTHENTICATION) + { + // To authorize against the Groups defined via the WL console, we need + // to have a SubjectPrincipal. Because we do not need a principal to authorize + // against web.xml / weblogic.xml, always save the SubjectPrincipal + principal = getSubjectPrincipal(username, password); + } + } + else // Code path for NIO endpoints. + { + principal = getSubjectPrincipal(username, password); + } + } + + return principal; + } + + /** + * Get a SubjectPrincipal for the current user. + * @return the generated SubjectPrincipal + */ + private Principal getSubjectPrincipal(String username, String password) + { + Principal principal=null; + + SimpleCallbackHandler handler = + new SimpleCallbackHandler(username, password); + try + { + Subject subject = Authentication.login(handler); + principal = new SubjectPrincipal(subject); + } + catch (LoginException e) + { + // let authentication fail if this fails + } + + return principal; + } + + /** + * Authorize a user against the Groups defined in the WL console. + * @param principal - Current user principal + * @param roles - Set of roles that allow a succesfull authorization + * @return true if the authorization were succesfull + */ + private boolean doSubjectGroupAuthorization(Principal principal, List roles) + { + boolean authorized = false; + + Subject subject = null; + if (principal instanceof SubjectPrincipal) + { + subject = ((SubjectPrincipal)principal).getSubject(); + } + else + { + subject = Security.getCurrentSubject(); + } + if (subject == null) + { + return false; + } + Iterator iter = roles.iterator(); + while (iter.hasNext()) + { + String role = (String)iter.next(); + if (SubjectUtils.isUserInGroup(subject, role)) + { + authorized = true; + break; + } + } + + return authorized; + } + + /** {@inheritDoc} */ + public boolean doAuthorization(Principal principal, List roles) + { + if (principal == null) + return false; // Avoid NPEs. + + //NOTE: I believe that both HttpServletRequest.isUserInRole and + //SubjectUtils.isUserInGroup returns if the user is in a Weblogic Group, + //not necessarily the Weblogic role construct + + boolean authorized = false; + + // Test for the presence of a response here (rather than request) because NIO + // endpoints require the alternate code path and they don't populate the response + // in FlexContext. + HttpServletResponse response = FlexContext.getHttpResponse(); + if (response != null) + { + HttpServletRequest request = FlexContext.getHttpRequest(); + + // This will attempt to authorize the user against roles configured + // in web.xml and weblogic.xml. + authorized = doAuthorization(principal, roles, request); + + // We also want to support roles defined via the WL console + // attempt this authorization here + if (!authorized) + { + authorized = doSubjectGroupAuthorization(principal, roles); + } + } + else // Code path for NIO endpoints. + { + authorized = doSubjectGroupAuthorization(principal, roles); + } + + return authorized; + } + + /** {@inheritDoc} */ + public boolean logout(Principal principal) + { + HttpServletResponse response = FlexContext.getHttpResponse(); + if (response != null) + { + // Destroy the Principal maintained by the app server. + HttpServletRequest request = FlexContext.getHttpRequest(); + ServletAuthentication.logout(request); + } + // else, current non-servlet session will be automatically invalidated, destroying any active Principal. + + return true; + } + + private class SubjectPrincipal implements Principal + { + private Subject subject; + + public SubjectPrincipal(Subject subject) + { + this.subject = subject; + } + + public String getName() + { + return SubjectUtils.getUserPrincipal(subject).getName(); + } + + public Subject getSubject() + { + return subject; + } + } + + /** {@inheritDoc} */ + public Principal convertPrincipal(Principal principal) + { + if (principal instanceof SubjectPrincipal) + { + return principal; + } + else + { + // We need to do the converting + Subject subject = Security.getCurrentSubject(); + return new SubjectPrincipal(subject); + } + } +} http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/fdbf19e4/opt/websphere/pom.xml ---------------------------------------------------------------------- diff --git a/opt/websphere/pom.xml b/opt/websphere/pom.xml new file mode 100644 index 0000000..dcf7d48 --- /dev/null +++ b/opt/websphere/pom.xml @@ -0,0 +1,55 @@ +<!-- + +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.flex.blazeds</groupId> + <artifactId>flex-messaging-opt</artifactId> + <version>4.7.0-SNAPSHOT</version> + </parent> + + <artifactId>flex-messaging-opt-webpshere</artifactId> + + <dependencies> + <dependency> + <groupId>com.ibm.websphere</groupId> + <artifactId>wsexception</artifactId> + <version>7.0 SP5</version> + <scope>system</scope> + <systemPath>${basedir}/../../lib/wsexception.jar</systemPath> + </dependency> + <dependency> + <groupId>com.ibm.websphere</groupId> + <artifactId>asynchbeans</artifactId> + <version>7.0 SP5</version> + <scope>system</scope> + <systemPath>${basedir}/../../lib/asynchbeans.jar</systemPath> + </dependency> + <dependency> + <groupId>com.ibm.websphere</groupId> + <artifactId>sas</artifactId> + <version>7.0 SP5</version> + <scope>system</scope> + <systemPath>${basedir}/../../lib/sas.jar</systemPath> + </dependency> + </dependencies> + +</project> http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/fdbf19e4/opt/websphere/src/main/java/flex/management/WebSphereMBeanServerLocator.java ---------------------------------------------------------------------- diff --git a/opt/websphere/src/main/java/flex/management/WebSphereMBeanServerLocator.java b/opt/websphere/src/main/java/flex/management/WebSphereMBeanServerLocator.java new file mode 100755 index 0000000..533f258 --- /dev/null +++ b/opt/websphere/src/main/java/flex/management/WebSphereMBeanServerLocator.java @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package flex.management; + +import java.lang.reflect.Method; + +import javax.management.MBeanServer; + +import flex.messaging.log.Log; +import flex.messaging.log.LogCategories; +import flex.messaging.util.ClassUtil; + +/** + * Custom MBeanServerLocator for use with WebSphere. + * This class locates a MBean server instance via WebSphere's administration APIs. + */ +public class WebSphereMBeanServerLocator implements MBeanServerLocator +{ + //-------------------------------------------------------------------------- + // + // Private Static Variables + // + //-------------------------------------------------------------------------- + + /** + * Localized error constant. + */ + private static final int FAILED_TO_LOCATE_MBEAN_SERVER = 10427; + + //-------------------------------------------------------------------------- + // + // Private Variables + // + //-------------------------------------------------------------------------- + + /** + * Reference to MBeanServer this locator found. + */ + private MBeanServer server; + + //-------------------------------------------------------------------------- + // + // Public Methods + // + //-------------------------------------------------------------------------- + + /** {@inheritDoc} */ + public synchronized MBeanServer getMBeanServer() + { + if (server == null) + { + Class adminServiceClass = ClassUtil.createClass("com.ibm.websphere.management.AdminServiceFactory"); + try + { + Method getMBeanFactoryMethod = adminServiceClass.getMethod("getMBeanFactory", new Class[0]); + Object mbeanFactory = getMBeanFactoryMethod.invoke(null, new Object[0]); + Method getMBeanServerMethod = mbeanFactory.getClass().getMethod("getMBeanServer", new Class[0]); + server = (MBeanServer)getMBeanServerMethod.invoke(mbeanFactory, new Object[0]); + } + catch (Exception e) + { + ManagementException me = new ManagementException(); + me.setMessage(FAILED_TO_LOCATE_MBEAN_SERVER, new Object[] {getClass().getName()}); + me.setRootCause(e); + throw me; + } + if (Log.isDebug()) + Log.getLogger(LogCategories.MANAGEMENT_MBEANSERVER).debug("Using MBeanServer: " + server); + } + return server; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/fdbf19e4/opt/websphere/src/main/java/flex/messaging/security/WebSphereLoginCommand.java ---------------------------------------------------------------------- diff --git a/opt/websphere/src/main/java/flex/messaging/security/WebSphereLoginCommand.java b/opt/websphere/src/main/java/flex/messaging/security/WebSphereLoginCommand.java new file mode 100755 index 0000000..cf02d26 --- /dev/null +++ b/opt/websphere/src/main/java/flex/messaging/security/WebSphereLoginCommand.java @@ -0,0 +1,273 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package flex.messaging.security; + +import com.ibm.websphere.security.UserRegistry; +import com.ibm.websphere.security.WSSecurityException; +import com.ibm.websphere.security.auth.WSLoginFailedException; +import com.ibm.ws.security.core.ContextManager; +import com.ibm.ws.security.core.ContextManagerFactory; +import flex.messaging.FlexContext; +import flex.messaging.log.Log; +import flex.messaging.log.LogCategories; + +import javax.security.auth.Subject; +import javax.servlet.http.HttpServletRequest; +import java.security.Principal; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/* + * To setup WebSphere 5.1 for authentication testing: + * + * 1) Install WebSphere 5.1 + * 2) Create two files, users.props and groups.props + * (examples in resources/security/websphere) and place them in a directory + * under your WS install. + * 3) Using the Admin webapp: + * + * Security > Global Security + * Check Enabled + * Check Enforce Java 2 Security + * Set Active User Registry to Custom + * Click OK + * + * Either the admin app will tell you to setup your Custom or you should + * go to Security > User Registries > Custom + * + * Server User ID should be one of your users from your users.props + * Server User Password should be the matching password from users.props + * Customer Registry Classname by default is com.ibm.websphere.security.FileRegistrySample + * Go to Custom Properties + * Add a prop "groupsFile" that points to your groups.props: e.g., c:/websphere5.1/AppServer/security/groups.props + * Add a prop "usersFile" that points to your users.props: e.g., c:/websphere5.1/AppServer/security/users.props + * + * Click OK + * + * 4) Install your Flex EAR. You may need to go into its Session Settings + * page and enable session security there? + * + * 5) In <websphere_dir>/java/jre/lib/security edit java.policy and add something + * like the following: + * +grant codeBase "file:${was.install.root}/installedApps/MCHOTIN03/Flex2Ear.ear/secure.war/-" { + permission java.security.AllPermission; +}; + + * This gives your webapp all the permissions it needs (possible that it could have + * been narrowed down further). + * + * 6) Edit java.security in teh same directory to add the following entries +security.provider.1=com.sun.net.ssl.internal.ssl.Provider +security.provider.2=sun.security.provider.Sun + * Update the entries below it so they're ordered right. + * Copy jsse.jar and jcert.jar into java/jre/lib/ext (I think) + * This will get the Flex Proxy to start correctly + * + * Restart your WebSphere, cross your fingers!!! + * + */ + +/** + * Authenticates against WebSphere but does not store the authenticated + * user in the HttpServletRequest for http attempts due to the container + * not providing a mechanism for access. + */ +public class WebSphereLoginCommand extends AppServerLoginCommand implements PrincipalConverter +{ + + /** {@inheritDoc} */ + public Principal doAuthentication(String username, Object credentials) + { + Principal principal = null; + try + { + String password = extractPassword(credentials); + + if (password != null) + { + ContextManager contextManager = ContextManagerFactory.getInstance(); + + Subject subject = + contextManager.login(contextManager.getDefaultRealm(), + username, password); + + if (subject != null) + { + //setting the caller subject really doesn't apply for long + //it appears to be removed later as each call to + //ContextManagerFactory.getInstance() + //returns a new instance and we cannot get the real context + //and assign values that will be re-used. + //this also means that the HttpServletRequest will not have the + //information that we've assigned, hence we store this contextManager + //in the Principal for later use + + contextManager.setCallerSubject(subject); + principal = new WSLCPrincipal(username, contextManager, subject); + } + } + } + catch (WSLoginFailedException wsLoginFailedException) + { + if (Log.isDebug()) + { + Log.getLogger(LogCategories.SECURITY).debug("WebSphereLoginCommand#doAuthentication() failed: " + wsLoginFailedException.toString(), wsLoginFailedException); + } + } + catch (WSSecurityException wsSecurityException) + { + if (Log.isDebug()) + { + Log.getLogger(LogCategories.SECURITY).debug("WebSphereLoginCommand#doAuthentication() failed: " + wsSecurityException.toString(), wsSecurityException); + } + } + + if (Log.isDebug() && principal != null) + { + Log.getLogger(LogCategories.SECURITY).debug("WebSphereLoginCommand#doAuthentication(). Principal: " + principal + ", Principal class: " + principal.getClass().getName() + + ", Principal identity: " + System.identityHashCode(principal)); + } + + return principal; + } + + /** {@inheritDoc} */ + public boolean doAuthorization(Principal principal, List roles) + { + //unfortunately we cannot seem to get the user stored + //in the context so the request will never have the information + //that we've assigned, therefore we have to do this + //every time + + if (principal == null) + return false; + + if (Log.isDebug()) + Log.getLogger(LogCategories.SECURITY).debug("WebSphereLoginCommand#doAuthorization(). Principal: " + principal + ", Principal class: " + principal.getClass().getName() + + ", Principal identity: " + System.identityHashCode(principal)); + + if (principal instanceof WSLCPrincipal) // This code path is hit if this login command handled authentication. + { + ContextManager contextManager = ((WSLCPrincipal)principal).getContextManager(); + UserRegistry registry = contextManager.getRegistry(contextManager.getDefaultRealm()); + + try + { + List groups = new ArrayList(registry.getGroupsForUser(principal.getName())); + + groups.retainAll(roles); + + // if authorization succeeds, set the user's Subject on this invocation context + // so that the rest of the Thread is executed in the context of the appropriate Subject + if (groups.size() > 0) + ContextManagerFactory.getInstance().setCallerSubject(((WSLCPrincipal)principal).getSubject()); + + return groups.size() > 0; + } + catch (Exception e) + { + } + } + else // This code path is hit if this login command didn't handle authentication. + { + // The Principal was not null, meaning we have a WAS Principal in the current HttpServletRequest. + // Use that for the authorization check. + HttpServletRequest request = FlexContext.getHttpRequest(); + for (Iterator iter = roles.iterator(); iter.hasNext(); ) + { + if (request.isUserInRole((String)iter.next())) + return true; + } + } + + return false; + } + + /** {@inheritDoc} */ + public boolean logout(Principal principal) + { + //as long as credentials are nulled since we can't store + //the authenticated user there's nothing to do + return true; + } + + private class WSLCPrincipal implements Principal + { + private String username; + private ContextManager contextManager; + private Subject subject; + + public WSLCPrincipal(String username, ContextManager contextManager, Subject subject) + { + this.username = username; + this.contextManager = contextManager; + this.subject = subject; + } + + public String getName() + { + return username; + } + + public ContextManager getContextManager() + { + return contextManager; + } + + public Subject getSubject() + { + return subject; + } + } + + /** {@inheritDoc} */ + public Principal convertPrincipal(Principal principal) + { + if (principal instanceof WSLCPrincipal) + { + // We are good + return principal; + } + else + { + // we need the converting + + ContextManager contextManager = ContextManagerFactory.getInstance(); + + Subject subject = null; + try + { + subject = contextManager.getCallerSubject(); + } + catch (WSSecurityException e) + { + + } + + if (subject != null) + { + return new WSLCPrincipal(principal.getName(), contextManager, subject); + } + else + // Just return the old one + return principal; + + } + } +} http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/fdbf19e4/opt/websphere/src/main/java/flex/messaging/util/concurrent/AsynchBeansWorkManagerExecutor.java ---------------------------------------------------------------------- diff --git a/opt/websphere/src/main/java/flex/messaging/util/concurrent/AsynchBeansWorkManagerExecutor.java b/opt/websphere/src/main/java/flex/messaging/util/concurrent/AsynchBeansWorkManagerExecutor.java new file mode 100755 index 0000000..a35c0e9 --- /dev/null +++ b/opt/websphere/src/main/java/flex/messaging/util/concurrent/AsynchBeansWorkManagerExecutor.java @@ -0,0 +1,231 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package flex.messaging.util.concurrent; + +import javax.naming.InitialContext; +import javax.naming.NamingException; + +import com.ibm.websphere.asynchbeans.Work; +import com.ibm.websphere.asynchbeans.WorkEvent; +import com.ibm.websphere.asynchbeans.WorkException; +import com.ibm.websphere.asynchbeans.WorkListener; +import com.ibm.websphere.asynchbeans.WorkManager; + +import flex.messaging.config.ConfigurationException; +import flex.messaging.log.Log; +import flex.messaging.log.LogCategories; + +/** + * Implements {@link Executor} by delegating command execution to a WAS asynchbeans <code>WorkManager</code>. + * For more information on the asynchbeans API, refer to the WAS Javadoc for + * <a href="http://publib.boulder.ibm.com/infocenter/wasinfo/v5r0/index.jsp?topic=/com.ibm.wasee.doc/info/ee/javadoc/ee/com/ibm/websphere/asynchbeans/WorkManager.html">WorkManager</a>. + * + * + */ +public class AsynchBeansWorkManagerExecutor implements Executor +{ + //-------------------------------------------------------------------------- + // + // Constructor + // + //-------------------------------------------------------------------------- + + /** + * Constructs an <code>AsynchBeansWorkManagerExecutor</code> that will delegate command execution + * to the specified <code>WorkManager</code> instance that is registered in JNDI. + * + * @param workManagerJNDIName The JNDI resource ref name for the <code>WorkManager</code>. + * @see com.ibm.websphere.asynchbeans.WorkManager + */ + public AsynchBeansWorkManagerExecutor(String workManagerJNDIName) + { + try + { + InitialContext ic = new InitialContext(); + workManager = (WorkManager)ic.lookup(workManagerJNDIName); + } + catch(NamingException ne) + { + ConfigurationException ce = new ConfigurationException(); + ce.setMessage(13600, new Object[] {workManagerJNDIName}); + ce.setRootCause(ne); + throw ce; + } + + workListener = new WorkListener() { + public void workAccepted(WorkEvent event) + { + /* No-op */ + } + public void workCompleted(WorkEvent event) + { + // This only needs to be handled if execution of the Runnable failed. + WorkException e = event.getException(); + if (e != null) + { + if (Log.isDebug()) + Log.getLogger(LogCategories.EXECUTOR).error("AsynchBeansWorkManager's WorkListener.workCompleted() callback invoked for failed execution.", e); + + handleFailedExecution(((WorkCommandWrapper)event.getWork()).command, e); + } + } + public void workRejected(WorkEvent event) + { + WorkException e = event.getException(); + if (Log.isDebug()) + Log.getLogger(LogCategories.EXECUTOR).error("AsynchBeansWorkManager's WorkListener.workRejected() callback invoked. WorkException? " + e); + + handleFailedExecution(((WorkCommandWrapper)event.getWork()).command, e); + } + public void workStarted(WorkEvent event) + { + /* No-op */ + } + }; + } + + //-------------------------------------------------------------------------- + // + // Variables + // + //-------------------------------------------------------------------------- + + /** + * Instance level lock for thread-safe state changes. + */ + private final Object lock = new Object(); + + /** + * Reference to the WorkManager instance configured in WAS that this executor instance delegates to. + */ + private final WorkManager workManager; + + /** + * Listener that monitors scheduled work for errors and notifies the FailedExecutionHandler if one has been set. + */ + private final WorkListener workListener; + + //-------------------------------------------------------------------------- + // + // Properties + // + //-------------------------------------------------------------------------- + + //---------------------------------- + // failedExecutionHandler + //---------------------------------- + + private FailedExecutionHandler failedExecutionHandler; + + /** {@inheritDoc} */ + public FailedExecutionHandler getFailedExecutionHandler() + { + synchronized (lock) + { + return failedExecutionHandler; + } + } + + /** {@inheritDoc} */ + public void setFailedExecutionHandler(FailedExecutionHandler value) + { + synchronized (lock) + { + failedExecutionHandler = value; + } + } + + //-------------------------------------------------------------------------- + // + // Public Methods + // + //-------------------------------------------------------------------------- + + /** {@inheritDoc} */ + public void execute(Runnable command) + { + try + { + // Register our listener to monitor each scheduled work, and set the start timeout for the work to indefinite (no queue timeout). + workManager.startWork(new WorkCommandWrapper(command), WorkManager.INDEFINITE, workListener); + } + catch (WorkException e) + { + handleFailedExecution(command, e); + } + } + + //-------------------------------------------------------------------------- + // + // Private Methods + // + //-------------------------------------------------------------------------- + + /** + * Handles command execution problems by notifying the FailedExecutionHandler if one has been set + * and otherwise logging the failure. + * + * @param command The command that failed to execute successfully. + * @param e The exception generated by the failed command. + */ + private void handleFailedExecution(Runnable command, Exception e) + { + FailedExecutionHandler handler = getFailedExecutionHandler(); + if (handler != null) + { + handler.failedExecution(command, this, e); + } + else if (Log.isError()) + { + Log.getLogger(LogCategories.EXECUTOR).error("AsynchBeansWorkManager hit an Exception but no FailedExecutionHandler is registered to handle the error.", e); + } + } + + //-------------------------------------------------------------------------- + // + // Inner Classes + // + //-------------------------------------------------------------------------- + + /** + * Helper class that wraps Runnable commands in the WAS Work interface. + */ + class WorkCommandWrapper implements Work + { + public WorkCommandWrapper(Runnable command) + { + this.command = command; + } + + private final Runnable command; + + public void run() + { + command.run(); + } + + /** + * This is invoked by WAS when the server is shutting down to signal long-running daemon threads spawned by the WorkManager + * to exit from their run() method. Our works are all short lived so this is a no-op; in this case WAS will force any + * works that are executing at server shutdown to terminate. + */ + public void release() + { + // No-op. + } + } +}
