Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 654C1200C1E for ; Fri, 17 Feb 2017 15:42:43 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id 60755160B55; Fri, 17 Feb 2017 14:42:43 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id B3FCA160B3F for ; Fri, 17 Feb 2017 15:42:41 +0100 (CET) Received: (qmail 27399 invoked by uid 500); 17 Feb 2017 14:42:40 -0000 Mailing-List: contact commits-help@flex.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@flex.apache.org Delivered-To: mailing list commits@flex.apache.org Received: (qmail 27391 invoked by uid 99); 17 Feb 2017 14:42:40 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 17 Feb 2017 14:42:40 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id A7C5DDFBD3; Fri, 17 Feb 2017 14:42:40 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: cdutz@apache.org To: commits@flex.apache.org Message-Id: <3a67f5b2f6cb4af28e85f2754ea138f5@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: flex-blazeds git commit: - Made BlazeDS use the ClassDeserializationValidator as default validator, if no validator is provided. - Adjusted the classes in the ClassDeserializationValidator default classes to explicitly list each class instead of using wi Date: Fri, 17 Feb 2017 14:42:40 +0000 (UTC) archived-at: Fri, 17 Feb 2017 14:42:43 -0000 Repository: flex-blazeds Updated Branches: refs/heads/develop e8560abcd -> f861f0993 - Made BlazeDS use the ClassDeserializationValidator as default validator, if no validator is provided. - Adjusted the classes in the ClassDeserializationValidator default classes to explicitly list each class instead of using wildcards. If you are getting errors, you need to explicitly list the classes you want to allow: ``` ... snip ... ``` Project: http://git-wip-us.apache.org/repos/asf/flex-blazeds/repo Commit: http://git-wip-us.apache.org/repos/asf/flex-blazeds/commit/f861f099 Tree: http://git-wip-us.apache.org/repos/asf/flex-blazeds/tree/f861f099 Diff: http://git-wip-us.apache.org/repos/asf/flex-blazeds/diff/f861f099 Branch: refs/heads/develop Commit: f861f0993c35e664906609cad275e45a71e2aaf1 Parents: e8560ab Author: Christofer Dutz Authored: Fri Feb 17 15:42:31 2017 +0100 Committer: Christofer Dutz Committed: Fri Feb 17 15:42:31 2017 +0100 ---------------------------------------------------------------------- .../main/java/flex/messaging/MessageBroker.java | 1 + .../config/ServerConfigurationParser.java | 27 ++- .../flex/messaging/io/SerializationContext.java | 1 + .../ClassDeserializationValidator.java | 184 ++++++++-------- .../test/java/amfclient/ClientCustomType.java | 45 ---- .../io/amf/client/AMFConnectionIT.java | 9 +- .../messaging/io/amf/client/AMFDataTypeIT.java | 208 ++++++++++++++++--- .../flex/messaging/util/TestServerWrapper.java | 17 +- .../remoting/amfclient/ClientCustomType.java | 45 ++++ .../services-config-customized-validation.xml | 65 ++++++ 10 files changed, 410 insertions(+), 192 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/f861f099/core/src/main/java/flex/messaging/MessageBroker.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/flex/messaging/MessageBroker.java b/core/src/main/java/flex/messaging/MessageBroker.java index 80b061e..3ffd2e4 100644 --- a/core/src/main/java/flex/messaging/MessageBroker.java +++ b/core/src/main/java/flex/messaging/MessageBroker.java @@ -57,6 +57,7 @@ import flex.messaging.util.RedeployManager; import flex.messaging.util.StringUtils; import flex.messaging.util.UUIDGenerator; import flex.messaging.util.UUIDUtils; +import flex.messaging.validators.ClassDeserializationValidator; import flex.messaging.validators.DeserializationValidator; import javax.servlet.ServletContext; http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/f861f099/core/src/main/java/flex/messaging/config/ServerConfigurationParser.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/flex/messaging/config/ServerConfigurationParser.java b/core/src/main/java/flex/messaging/config/ServerConfigurationParser.java index 9ff3e1c..e8eb1a9 100644 --- a/core/src/main/java/flex/messaging/config/ServerConfigurationParser.java +++ b/core/src/main/java/flex/messaging/config/ServerConfigurationParser.java @@ -16,6 +16,7 @@ */ package flex.messaging.config; +import flex.messaging.validators.ClassDeserializationValidator; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -1865,21 +1866,37 @@ public abstract class ServerConfigurationParser extends AbstractConfigurationPar private void validators(Node root) { Node validatorsNode = selectSingleNode(root, VALIDATORS_ELEMENT); - if (validatorsNode == null) + if (validatorsNode == null) { + // Default to the ClassDeserializationValidator + defaultValidator(); return; + } // Validation allowedChildElements(validatorsNode, VALIDATORS_CHILDREN); // Validator NodeList validators = selectNodeList(validatorsNode, VALIDATOR_ELEMENT); - for (int i = 0; i < validators.getLength(); i++) - { - Node validator = validators.item(i); - validator(validator); + if(validators.getLength() > 0) { + for (int i = 0; i < validators.getLength(); i++) { + Node validator = validators.item(i); + validator(validator); + } + } else { + // Default to the ClassDeserializationValidator + defaultValidator(); } } + /** + * Initialize a efault validator that protects BlazeDS against the most obvious attacks. + */ + private void defaultValidator() { + ValidatorSettings validatorSettings = new ValidatorSettings(); + validatorSettings.setClassName(ClassDeserializationValidator.class.getName()); + ((MessagingConfiguration)config).addValidatorSettings(validatorSettings); + } + private void validator(Node validator) { // Validation http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/f861f099/core/src/main/java/flex/messaging/io/SerializationContext.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/flex/messaging/io/SerializationContext.java b/core/src/main/java/flex/messaging/io/SerializationContext.java index 79bb2d7..64196cc 100644 --- a/core/src/main/java/flex/messaging/io/SerializationContext.java +++ b/core/src/main/java/flex/messaging/io/SerializationContext.java @@ -17,6 +17,7 @@ package flex.messaging.io; import flex.messaging.util.ClassUtil; +import flex.messaging.validators.ClassDeserializationValidator; import flex.messaging.validators.DeserializationValidator; import java.io.Serializable; http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/f861f099/core/src/main/java/flex/messaging/validators/ClassDeserializationValidator.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/flex/messaging/validators/ClassDeserializationValidator.java b/core/src/main/java/flex/messaging/validators/ClassDeserializationValidator.java index cf07942..ed2ac80 100644 --- a/core/src/main/java/flex/messaging/validators/ClassDeserializationValidator.java +++ b/core/src/main/java/flex/messaging/validators/ClassDeserializationValidator.java @@ -16,23 +16,18 @@ */ package flex.messaging.validators; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.regex.Pattern; - import flex.messaging.config.ConfigMap; +import java.util.*; +import java.util.regex.Pattern; + /** * The ClassDeserializationValidator is provided as a default * implementation of DeserializationValidator and it simply * validates the creation of allowed and disallowed classes as specified in * the configuration. */ -public class ClassDeserializationValidator implements DeserializationValidator -{ +public class ClassDeserializationValidator implements DeserializationValidator { //-------------------------------------------------------------------------- // // Public Static Constants @@ -43,25 +38,36 @@ public class ClassDeserializationValidator implements DeserializationValidator public static final String PROPERTY_DISALLOW_CLASSES = "disallow-classes"; public static final String PROPERTY_CLASS_ATTR = "class"; public static final String PROPERTY_NAME_ATTR = "name"; - - private static final String [] DEFAULT_ALLOW_CLASSES = { - "flex.messaging.*", - "flex.data.*", - "java.lang.Boolean", - "java.lang.Byte", - "java.lang.Character", - "java.lang.Double", - "java.lang.Float", - "java.lang.Integer", - "java.lang.Long", - "java.lang.Object", - "java.lang.Short", - "java.lang.String", - "java.io.Externalizable", - "java.util.*", - "org.w3c.dom.Document", - "\\[B", - "\\[Ljava.lang.Object;" + + private static final String[] DEFAULT_ALLOW_CLASSES = { + "flex.messaging.io.amf.SerializedObject", + "flex.messaging.io.ArrayCollection", + "flex.messaging.io.ObjectProxy", + "flex.messaging.io.SerializationProxy", + "flex.messaging.messages.AcknowledgeMessageExt", + "flex.messaging.messages.AsyncMessageExt", + "flex.messaging.messages.CommandMessageExt", + "flex.data.messages.DataMessageExt", + "flex.data.messages.ManagedRemotingMessageExt", + "flex.data.messages.PagedMessageExt", + "flex.data.messages.SequencedMessageExt", + "flex.data.messages.UpdateCollectionMessageExt", + "flex.data.ChangedItems", + "java.lang.Boolean", + "java.lang.Byte", + "java.lang.Character", + "java.lang.Double", + "java.lang.Float", + "java.lang.Integer", + "java.lang.Long", + "java.lang.Object", + "java.lang.Short", + "java.lang.String", + "java.io.Externalizable", + "java.util.Date", + "org.w3c.dom.Document", + "\\[B", + "\\[Ljava.lang.Object;" }; //-------------------------------------------------------------------------- @@ -87,6 +93,10 @@ public class ClassDeserializationValidator implements DeserializationValidator private Map allowClassPatterns; private Map disallowClassPatterns; + public ClassDeserializationValidator() { + } + + //-------------------------------------------------------------------------- // // Public Methods @@ -98,10 +108,8 @@ public class ClassDeserializationValidator implements DeserializationValidator * * @param classNamePattern The name of the class which can be a regular expression. */ - public void addAllowClassPattern(String classNamePattern) - { - synchronized (lock) - { + public void addAllowClassPattern(String classNamePattern) { + synchronized (lock) { if (allowClassPatterns == null) allowClassPatterns = new HashMap(); @@ -116,10 +124,8 @@ public class ClassDeserializationValidator implements DeserializationValidator * * @param classNamePattern The name of the class which can be a regular expression. */ - public void removeAllowClassPattern(String classNamePattern) - { - synchronized (lock) - { + public void removeAllowClassPattern(String classNamePattern) { + synchronized (lock) { if (allowClassPatterns != null) allowClassPatterns.remove(classNamePattern); @@ -132,10 +138,8 @@ public class ClassDeserializationValidator implements DeserializationValidator * * @param classNamePattern The name of the class which can be a regular expression. */ - public void addDisallowClassPattern(String classNamePattern) - { - synchronized (lock) - { + public void addDisallowClassPattern(String classNamePattern) { + synchronized (lock) { if (disallowClassPatterns == null) disallowClassPatterns = new HashMap(); @@ -150,10 +154,8 @@ public class ClassDeserializationValidator implements DeserializationValidator * * @param classNamePattern The name of the class which can be a regular expression. */ - public void removeDisallowClassPattern(String classNamePattern) - { - synchronized (lock) - { + public void removeDisallowClassPattern(String classNamePattern) { + synchronized (lock) { if (disallowClassPatterns != null) disallowClassPatterns.remove(classNamePattern); @@ -167,12 +169,11 @@ public class ClassDeserializationValidator implements DeserializationValidator * therefore this method always returns true. * * @param instance The Array or List instance. - * @param index The index at which the value is being assigned. - * @param value The value that is assigned to the index. + * @param index The index at which the value is being assigned. + * @param value The value that is assigned to the index. * @return True. */ - public boolean validateAssignment(Object instance, int index, Object value) - { + public boolean validateAssignment(Object instance, int index, Object value) { return true; } @@ -181,13 +182,12 @@ public class ClassDeserializationValidator implements DeserializationValidator * to a value but this class only deals with class creations, therefore this * method always returns true. * - * @param instance The instance with the property that is being assigned a new value. + * @param instance The instance with the property that is being assigned a new value. * @param propertyName The name of the property that is being assigned. - * @param value The value that the property is being assigned to. + * @param value The value that the property is being assigned to. * @return True. */ - public boolean validateAssignment(Object instance, String propertyName, Object value) - { + public boolean validateAssignment(Object instance, String propertyName, Object value) { return true; } @@ -199,9 +199,8 @@ public class ClassDeserializationValidator implements DeserializationValidator * @param c The class that is being created. * @return True if the creation is valid. */ - public boolean validateCreation(Class c) - { - String className = c == null? null : c.getName(); + public boolean validateCreation(Class c) { + String className = c == null ? null : c.getName(); if (className == null) return true; @@ -217,12 +216,9 @@ public class ClassDeserializationValidator implements DeserializationValidator // go through the disallow and allow class patterns list. // Disallow the class if there's a disallow-classes list, and the class is in that list. - if (disallowClassPatterns != null && !disallowClassPatterns.isEmpty()) - { - for (Pattern pattern : disallowClassPatterns.values()) - { - if (pattern.matcher(className).matches()) - { + if (disallowClassPatterns != null && !disallowClassPatterns.isEmpty()) { + for (Pattern pattern : disallowClassPatterns.values()) { + if (pattern.matcher(className).matches()) { addDisallowClass(className); return false; } @@ -230,12 +226,9 @@ public class ClassDeserializationValidator implements DeserializationValidator } // Disallow the class if there's an allowed-classes list, and the class is NOT in that list. - if (allowClassPatterns != null && !allowClassPatterns.isEmpty()) - { - for (Pattern pattern : allowClassPatterns.values()) - { - if (pattern.matcher(className).matches()) - { + if (allowClassPatterns != null && !allowClassPatterns.isEmpty()) { + for (Pattern pattern : allowClassPatterns.values()) { + if (pattern.matcher(className).matches()) { addAllowClass(className); return true; } @@ -250,28 +243,25 @@ public class ClassDeserializationValidator implements DeserializationValidator return true; } - /** {@inheritDoc} */ - public void initialize(String id, ConfigMap properties) - { + /** + * {@inheritDoc} + */ + public void initialize(String id, ConfigMap properties) { // Apply default allow classes - for (String defaultAllowClassPattern : DEFAULT_ALLOW_CLASSES) - { + for (String defaultAllowClassPattern : DEFAULT_ALLOW_CLASSES) { addAllowClassPattern(defaultAllowClassPattern); } - + if (properties == null || properties.size() == 0) return; // Process allow-classes. ConfigMap allowedClassesMap = properties.getPropertyAsMap(PROPERTY_ALLOW_CLASSES, null); - if (allowedClassesMap != null && !allowedClassesMap.isEmpty()) - { + if (allowedClassesMap != null && !allowedClassesMap.isEmpty()) { List names = allowedClassesMap.getPropertyAsList(PROPERTY_CLASS_ATTR, null); - if (names != null && !names.isEmpty()) - { - for (Object element : names) - { - String name = ((ConfigMap)element).getProperty(PROPERTY_NAME_ATTR); + if (names != null && !names.isEmpty()) { + for (Object element : names) { + String name = ((ConfigMap) element).getProperty(PROPERTY_NAME_ATTR); addAllowClassPattern(name); } } @@ -279,14 +269,11 @@ public class ClassDeserializationValidator implements DeserializationValidator // Process disallow-classes. ConfigMap disallowedClassesMap = properties.getPropertyAsMap(PROPERTY_DISALLOW_CLASSES, null); - if (disallowedClassesMap != null && !disallowedClassesMap.isEmpty()) - { + if (disallowedClassesMap != null && !disallowedClassesMap.isEmpty()) { List names = disallowedClassesMap.getPropertyAsList(PROPERTY_CLASS_ATTR, null); - if (names != null && !names.isEmpty()) - { - for (Object element : names) - { - String name = ((ConfigMap)element).getProperty(PROPERTY_NAME_ATTR); + if (names != null && !names.isEmpty()) { + for (Object element : names) { + String name = ((ConfigMap) element).getProperty(PROPERTY_NAME_ATTR); addDisallowClassPattern(name); } } @@ -299,10 +286,8 @@ public class ClassDeserializationValidator implements DeserializationValidator // //-------------------------------------------------------------------------- - protected void addAllowClass(String className) - { - synchronized (lock) - { + protected void addAllowClass(String className) { + synchronized (lock) { if (allowClasses == null) allowClasses = new HashSet(); @@ -311,10 +296,8 @@ public class ClassDeserializationValidator implements DeserializationValidator } } - protected void addDisallowClass(String className) - { - synchronized (lock) - { + protected void addDisallowClass(String className) { + synchronized (lock) { if (disallowClasses == null) disallowClasses = new HashSet(); @@ -322,15 +305,12 @@ public class ClassDeserializationValidator implements DeserializationValidator disallowClasses.add(className); } } - - protected void clearClassCache() - { - if (allowClasses != null) - { + + protected void clearClassCache() { + if (allowClasses != null) { allowClasses.clear(); } - if (disallowClasses != null) - { + if (disallowClasses != null) { disallowClasses.clear(); } } http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/f861f099/remoting/src/test/java/amfclient/ClientCustomType.java ---------------------------------------------------------------------- diff --git a/remoting/src/test/java/amfclient/ClientCustomType.java b/remoting/src/test/java/amfclient/ClientCustomType.java deleted file mode 100644 index 0e5bd46..0000000 --- a/remoting/src/test/java/amfclient/ClientCustomType.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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 amfclient; - -/** - * The client side object used by the AMFConnectionIT. There is a corresponding - * server side object. - */ -public class ClientCustomType -{ - private int id; - - public ClientCustomType() - { - } - - public int getId() - { - return id; - } - - public void setId(int id) - { - this.id = id; - } - - public String toString() - { - return "ClientCustomType: " + id; - } -} http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/f861f099/remoting/src/test/java/flex/messaging/io/amf/client/AMFConnectionIT.java ---------------------------------------------------------------------- diff --git a/remoting/src/test/java/flex/messaging/io/amf/client/AMFConnectionIT.java b/remoting/src/test/java/flex/messaging/io/amf/client/AMFConnectionIT.java index 134315c..b2d3bef 100644 --- a/remoting/src/test/java/flex/messaging/io/amf/client/AMFConnectionIT.java +++ b/remoting/src/test/java/flex/messaging/io/amf/client/AMFConnectionIT.java @@ -28,7 +28,7 @@ import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; -import amfclient.ClientCustomType; +import remoting.amfclient.ClientCustomType; import flex.messaging.MessageException; import flex.messaging.messages.RemotingMessage; @@ -116,7 +116,7 @@ public class AMFConnectionIT extends TestCase } AMFConnection.registerAlias( "remoting.amfclient.ServerCustomType" /* server type */, - "amfclient.ClientCustomType" /* client type */); + "remoting.amfclient.ClientCustomType" /* client type */); } protected void tearDown() throws Exception { serverWrapper.stopServer(); @@ -329,11 +329,9 @@ public class AMFConnectionIT extends TestCase public void testCallNonexistantMethod() { String method = "nonExistantMethod"; - final ClientCustomType methodArg = new ClientCustomType(); - methodArg.setId(1); try { - internalTestCall(getOperationCall(method), methodArg, new CallResultHandler(){ + internalTestCall(getOperationCall(method), "Wombat", new CallResultHandler(){ public void onResult(Object result) { fail("Unexcepted result: " + result); @@ -382,6 +380,7 @@ public class AMFConnectionIT extends TestCase fail(UNEXPECTED_EXCEPTION_STRING + e); } } + public void testCloseNoConnect() { AMFConnection amfConnection = new AMFConnection(); http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/f861f099/remoting/src/test/java/flex/messaging/io/amf/client/AMFDataTypeIT.java ---------------------------------------------------------------------- diff --git a/remoting/src/test/java/flex/messaging/io/amf/client/AMFDataTypeIT.java b/remoting/src/test/java/flex/messaging/io/amf/client/AMFDataTypeIT.java index 0347a20..d9d9058 100644 --- a/remoting/src/test/java/flex/messaging/io/amf/client/AMFDataTypeIT.java +++ b/remoting/src/test/java/flex/messaging/io/amf/client/AMFDataTypeIT.java @@ -29,7 +29,7 @@ import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; -import amfclient.ClientCustomType; +import remoting.amfclient.ClientCustomType; import flex.messaging.io.amf.client.exceptions.ClientStatusException; import flex.messaging.io.amf.client.exceptions.ServerStatusException; @@ -47,9 +47,12 @@ public class AMFDataTypeIT extends TestCase private static final String DEFAULT_URL = "http://localhost:%s/qa-regress/messagebroker/amf"; private static final String DEFAULT_AMF_OPERATION = getOperationCall(DEFAULT_METHOD_NAME); private static final String UNEXPECTED_EXCEPTION_STRING = "Unexpected exception: "; + private static final String UNEXPECTED_SUCCESS_STRING = "Unexpected success of previous operation"; - private static TestServerWrapper serverWrapper; - private static int serverPort; + private static TestServerWrapper standardValidationServerWrapper; + private static int standardValidationServerPort; + private static TestServerWrapper customValidationServerWrapper; + private static int customValidationServerPort; private static SerializationContext serializationContext; /** @@ -61,10 +64,13 @@ public class AMFDataTypeIT extends TestCase return DEFAULT_DESTINATION_ID + "." + method; } - protected String getConnectionUrl() { - return String.format(DEFAULT_URL, serverPort); + protected String getStandardValidationConnectionUrl() { + return String.format(DEFAULT_URL, standardValidationServerPort); } + protected String getCustomValidationConnectionUrl() { + return String.format(DEFAULT_URL, customValidationServerPort); + } public AMFDataTypeIT(String name) { @@ -93,17 +99,29 @@ public class AMFDataTypeIT extends TestCase suite.addTest(new AMFDataTypeIT("testXMLDocumentEnabledXml")); suite.addTest(new AMFDataTypeIT("testXMLDocumentDisabledXml")); + suite.addTest(new AMFDataTypeIT("testCallObjectArgObjectReturnCustomizedValidation")); + suite.addTest(new AMFDataTypeIT("testCallCustomArgObjectReturnCustomizedValidation")); + suite.addTest(new AMFDataTypeIT("testCallObjectArgCustomReturnCustomizedValidation")); + suite.addTest(new AMFDataTypeIT("testCallCustomArgCustomReturnCustomizedValidation")); + suite.addTest(new AMFDataTypeIT("testCallObjectArrayArgObjectArrayReturnCustomizedValidation")); return new TestSetup(suite) { protected void setUp() throws Exception { - serverWrapper = new TestServerWrapper(); - serverPort = serverWrapper.startServer("classpath:/WEB-INF/flex/services-config.xml"); - if(serverPort == -1) { - Assert.fail("Couldn't start server process"); + standardValidationServerWrapper = new TestServerWrapper(); + standardValidationServerPort = standardValidationServerWrapper.startServer("classpath:/WEB-INF/flex/services-config.xml"); + if(standardValidationServerPort == -1) { + Assert.fail("Couldn't start server (standard validation) process"); + } + + customValidationServerWrapper = new TestServerWrapper(); + customValidationServerPort = customValidationServerWrapper.startServer("classpath:/WEB-INF/flex/services-config-customized-validation.xml"); + if(customValidationServerPort == -1) { + Assert.fail("Couldn't start server (custom validation) process"); } + AMFConnection.registerAlias( "remoting.amfclient.ServerCustomType" /* server type */, - "amfclient.ClientCustomType" /* client type */); + "remoting.amfclient.ClientCustomType" /* client type */); serializationContext = new SerializationContext(); serializationContext.createASObjectForMissingType = true; @@ -117,8 +135,10 @@ public class AMFDataTypeIT extends TestCase serializationContext.allowXml = false; } protected void tearDown() throws Exception { - serverWrapper.stopServer(); - serverWrapper = null; + standardValidationServerWrapper.stopServer(); + standardValidationServerWrapper = null; + customValidationServerWrapper.stopServer(); + customValidationServerWrapper = null; } }; } @@ -132,7 +152,7 @@ public class AMFDataTypeIT extends TestCase { Assert.assertEquals(DEFAULT_METHOD_ARG, result); } - }); + }, false); } catch (Exception e) { @@ -151,7 +171,7 @@ public class AMFDataTypeIT extends TestCase { Assert.assertEquals(methodArg, ((Double)result).intValue()); } - }); + }, false); } catch (Exception e) { @@ -170,7 +190,7 @@ public class AMFDataTypeIT extends TestCase { Assert.assertEquals(methodArg, result); } - }); + }, false); } catch (Exception e) { @@ -189,7 +209,7 @@ public class AMFDataTypeIT extends TestCase { Assert.assertEquals(methodArg, result); } - }); + }, false); } catch (Exception e) { @@ -208,7 +228,7 @@ public class AMFDataTypeIT extends TestCase { Assert.assertEquals(methodArg, ((Double)result).shortValue()); } - }); + }, false); } catch (Exception e) { @@ -227,7 +247,7 @@ public class AMFDataTypeIT extends TestCase { Assert.assertEquals(methodArg, result); } - }); + }, false); } catch (Exception e) { @@ -249,7 +269,30 @@ public class AMFDataTypeIT extends TestCase ClientCustomType temp2 = (ClientCustomType)result; Assert.assertEquals(1, temp2.getId()); } - }); + }, false); + fail(UNEXPECTED_SUCCESS_STRING); + } + catch (Exception e) + { + // An exception is what we expect here. + } + } + + public void testCallObjectArgObjectReturnCustomizedValidation() + { + String method = "echoObject1"; + ClientCustomType temp = new ClientCustomType(); + temp.setId(1); + final Object methodArg = temp; + try + { + internalTestCall(getOperationCall(method), methodArg, new CallResultHandler(){ + public void onResult(Object result) + { + ClientCustomType temp2 = (ClientCustomType)result; + Assert.assertEquals(1, temp2.getId()); + } + }, true); } catch (Exception e) { @@ -271,7 +314,30 @@ public class AMFDataTypeIT extends TestCase ClientCustomType temp2 = (ClientCustomType)result; Assert.assertEquals(1, temp2.getId()); } - }); + }, false); + fail(UNEXPECTED_SUCCESS_STRING); + } + catch (Exception e) + { + // An exception is what we expect here. + } + } + + public void testCallObjectArgCustomReturnCustomizedValidation() + { + String method = "echoObject2"; + ClientCustomType temp = new ClientCustomType(); + temp.setId(1); + final Object methodArg = temp; + try + { + internalTestCall(getOperationCall(method), methodArg, new CallResultHandler(){ + public void onResult(Object result) + { + ClientCustomType temp2 = (ClientCustomType)result; + Assert.assertEquals(1, temp2.getId()); + } + }, true); } catch (Exception e) { @@ -292,7 +358,29 @@ public class AMFDataTypeIT extends TestCase ClientCustomType temp2 = (ClientCustomType)result; Assert.assertEquals(1, temp2.getId()); } - }); + }, false); + fail(UNEXPECTED_SUCCESS_STRING); + } + catch (Exception e) + { + // An exception is what we expect here. + } + } + + public void testCallCustomArgObjectReturnCustomizedValidation() + { + String method = "echoObject3"; + final ClientCustomType methodArg = new ClientCustomType(); + methodArg.setId(1); + try + { + internalTestCall(getOperationCall(method), methodArg, new CallResultHandler(){ + public void onResult(Object result) + { + ClientCustomType temp2 = (ClientCustomType)result; + Assert.assertEquals(1, temp2.getId()); + } + }, true); } catch (Exception e) { @@ -313,7 +401,29 @@ public class AMFDataTypeIT extends TestCase ClientCustomType temp2 = (ClientCustomType)result; Assert.assertEquals(1, temp2.getId()); } - }); + }, false); + fail(UNEXPECTED_SUCCESS_STRING); + } + catch (Exception e) + { + // An exception is what we expect here. + } + } + + public void testCallCustomArgCustomReturnCustomizedValidation() + { + String method = "echoObject4"; + final ClientCustomType methodArg = new ClientCustomType(); + methodArg.setId(1); + try + { + internalTestCall(getOperationCall(method), methodArg, new CallResultHandler(){ + public void onResult(Object result) + { + ClientCustomType temp2 = (ClientCustomType)result; + Assert.assertEquals(1, temp2.getId()); + } + }, true); } catch (Exception e) { @@ -332,7 +442,7 @@ public class AMFDataTypeIT extends TestCase ClientCustomType temp2 = (ClientCustomType)result; Assert.assertEquals(1, temp2.getId()); } - }); + }, false); } catch (Exception e) { @@ -351,7 +461,7 @@ public class AMFDataTypeIT extends TestCase ClientCustomType temp2 = (ClientCustomType)result; Assert.assertEquals(1, temp2.getId()); } - }); + }, false); } catch (Exception e) { @@ -374,7 +484,7 @@ public class AMFDataTypeIT extends TestCase Assert.assertEquals(i, temp2.getId()); } } - }); + }, false); } catch (Exception e) { @@ -397,7 +507,7 @@ public class AMFDataTypeIT extends TestCase Assert.assertEquals(i, ((Integer)temp.get(i)).intValue()); } } - }); + }, false); } catch (Exception e) { @@ -428,7 +538,39 @@ public class AMFDataTypeIT extends TestCase Assert.assertEquals(i, temp2.getId()); } } - }); + }, false); + fail(UNEXPECTED_SUCCESS_STRING); + } + catch (Exception e) + { + // An exception is what we expect here. + } + } + + public void testCallObjectArrayArgObjectArrayReturnCustomizedValidation() + { + String method = "echoObject1"; + Object[] temp = new Object[3]; + for (int i = 0; i < temp.length; i++) + { + ClientCustomType cct = new ClientCustomType(); + cct.setId(i); + temp[i] = cct; + } + final Object[] methodArg = temp; + try + { + internalTestCall(getOperationCall(method), methodArg, new CallResultHandler(){ + public void onResult(Object result) + { + List temp = (List)result; + for (int i = 0; i < temp.size(); i++) + { + ClientCustomType temp2 = (ClientCustomType)temp.get(i); + Assert.assertEquals(i, temp2.getId()); + } + } + }, true); } catch (Exception e) { @@ -464,7 +606,7 @@ public class AMFDataTypeIT extends TestCase fail(UNEXPECTED_EXCEPTION_STRING + e); } } - }); + }, false); } catch (Exception e) { @@ -501,7 +643,7 @@ public class AMFDataTypeIT extends TestCase fail(UNEXPECTED_EXCEPTION_STRING + e); } } - }); + }, false); } catch (Exception e) { @@ -517,11 +659,15 @@ public class AMFDataTypeIT extends TestCase // Helper method used by JUnit tests to pass in an operation and method argument // When the AMF call returns, CallResultHandler.onResult is called to Assert things. - private void internalTestCall(String operation, Object methodArg, CallResultHandler resultHandler) throws ClientStatusException, ServerStatusException + private void internalTestCall(String operation, Object methodArg, CallResultHandler resultHandler, boolean customizedValidation) throws ClientStatusException, ServerStatusException { AMFConnection amfConnection = new AMFConnection(); // Connect. - amfConnection.connect(getConnectionUrl(), serializationContext); + if(customizedValidation) { + amfConnection.connect(getCustomValidationConnectionUrl(), serializationContext); + } else { + amfConnection.connect(getStandardValidationConnectionUrl(), serializationContext); + } // Make a remoting call and retrieve the result. Object result; if (methodArg == null) http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/f861f099/remoting/src/test/java/flex/messaging/util/TestServerWrapper.java ---------------------------------------------------------------------- diff --git a/remoting/src/test/java/flex/messaging/util/TestServerWrapper.java b/remoting/src/test/java/flex/messaging/util/TestServerWrapper.java index ca1c17b..4dc3c02 100644 --- a/remoting/src/test/java/flex/messaging/util/TestServerWrapper.java +++ b/remoting/src/test/java/flex/messaging/util/TestServerWrapper.java @@ -19,6 +19,9 @@ package flex.messaging.util; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; /** * Simple little wrapper starting up a BlazeDS server in a separate VM useful for unit testing the @@ -37,11 +40,17 @@ public class TestServerWrapper { final String separator = System.getProperty("file.separator"); final String classpath = System.getProperty("java.class.path"); final String path = System.getProperty("java.home") + separator + "bin" + separator + "java"; + List args = new LinkedList(); + args.add(path); +/* if(configPath.contains("customized-validation")) { + args.add("-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005"); + }*/ + args.add("-cp"); + args.add(classpath); + args.add(TestServer.class.getCanonicalName()); + args.add(configPath); System.out.print("Starting test-server"); - final ProcessBuilder processBuilder = new ProcessBuilder(path, - //"-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005", - "-cp", /*"\"" +*/ classpath /*+ "\""*/, - TestServer.class.getCanonicalName(), /*"\"" +*/ configPath /*+ "\""*/); + final ProcessBuilder processBuilder = new ProcessBuilder(args.toArray(new String[0])); processBuilder.redirectErrorStream(true); try { serverProcess = processBuilder.start(); http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/f861f099/remoting/src/test/java/remoting/amfclient/ClientCustomType.java ---------------------------------------------------------------------- diff --git a/remoting/src/test/java/remoting/amfclient/ClientCustomType.java b/remoting/src/test/java/remoting/amfclient/ClientCustomType.java new file mode 100644 index 0000000..2023bdf --- /dev/null +++ b/remoting/src/test/java/remoting/amfclient/ClientCustomType.java @@ -0,0 +1,45 @@ +/* + * 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 remoting.amfclient; + +/** + * The client side object used by the AMFConnectionIT. There is a corresponding + * server side object. + */ +public class ClientCustomType +{ + private int id; + + public ClientCustomType() + { + } + + public int getId() + { + return id; + } + + public void setId(int id) + { + this.id = id; + } + + public String toString() + { + return "ClientCustomType: " + id; + } +} http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/f861f099/remoting/src/test/resources/WEB-INF/flex/services-config-customized-validation.xml ---------------------------------------------------------------------- diff --git a/remoting/src/test/resources/WEB-INF/flex/services-config-customized-validation.xml b/remoting/src/test/resources/WEB-INF/flex/services-config-customized-validation.xml new file mode 100644 index 0000000..9832eff --- /dev/null +++ b/remoting/src/test/resources/WEB-INF/flex/services-config-customized-validation.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + + + + + [BlazeDS] + false + false + false + false + + + Endpoint.* + Service.* + Configuration + + + + +