1 /* 2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 import java.io.InvalidClassException; 25 import java.io.Serializable; 26 27 import java.rmi.Remote; 28 import java.rmi.RemoteException; 29 import java.rmi.UnmarshalException; 30 31 import java.util.Objects; 32 33 import sun.misc.ObjectInputFilter; 34 import sun.rmi.server.UnicastServerRef; 35 import sun.rmi.server.UnicastServerRef2; 36 import sun.rmi.transport.LiveRef; 37 38 import org.testng.Assert; 39 import org.testng.annotations.DataProvider; 40 import org.testng.annotations.Test; 41 42 /* 43 * @test 44 * @modules java.rmi/sun.rmi.registry 45 * java.rmi/sun.rmi.server 46 * java.rmi/sun.rmi.transport 47 * java.rmi/sun.rmi.transport.tcp 48 * @run testng/othervm FilterUSRTest 49 * @summary Check objects exported with ObjectInputFilters via internal UnicastServerRef(2) 50 */ 51 public class FilterUSRTest { 52 53 /** 54 * Data to test serialFilter call counts. 55 * - name 56 * - Object 57 * - expected count of calls to checkInput. 58 * 59 * @return array of test data 60 */ 61 @DataProvider(name = "bindData") bindObjects()62 static Object[][] bindObjects() { 63 Object[][] data = { 64 {"SimpleString", "SimpleString", 0}, 65 {"String", new XX("now is the time"), 1}, 66 {"String[]", new XX(new String[3]), 3}, 67 {"Long[4]", new XX(new Long[4]), 3}, 68 {"RejectME", new XX(new RejectME()), -1}, 69 }; 70 return data; 71 } 72 73 /* 74 * Test exporting an object with a serialFilter using UnicastServerRef.exportObject(). 75 * Send some objects and check the number of calls to the serialFilter. 76 */ 77 @Test(dataProvider = "bindData") UnicastServerRef(String name, Object obj, int expectedFilterCount)78 public void UnicastServerRef(String name, Object obj, int expectedFilterCount) throws RemoteException { 79 try { 80 RemoteImpl impl = RemoteImpl.create(); 81 UnicastServerRef ref = new UnicastServerRef(new LiveRef(0), impl.checker); 82 83 Echo client = (Echo) ref.exportObject(impl, null, false); 84 85 int count = client.filterCount(obj); 86 System.out.printf("count: %d, obj: %s%n", count, obj); 87 Assert.assertEquals(count, expectedFilterCount, "wrong number of filter calls"); 88 } catch (RemoteException rex) { 89 if (expectedFilterCount == -1 && 90 UnmarshalException.class.equals(rex.getCause().getClass()) && 91 InvalidClassException.class.equals(rex.getCause().getCause().getClass())) { 92 return; // normal expected exception 93 } 94 rex.printStackTrace(); 95 Assert.fail("unexpected remote exception", rex); 96 } catch (Exception ex) { 97 Assert.fail("unexpected exception", ex); 98 } 99 } 100 101 /* 102 * Test exporting an object with a serialFilter using UnicastServerRef2.exportObject() 103 * with explicit (but null) SocketFactories. 104 * Send some objects and check the number of calls to the serialFilter. 105 */ 106 @Test(dataProvider = "bindData") UnicastServerRef2(String name, Object obj, int expectedFilterCount)107 public void UnicastServerRef2(String name, Object obj, int expectedFilterCount) throws RemoteException { 108 try { 109 RemoteImpl impl = RemoteImpl.create(); 110 UnicastServerRef2 ref = new UnicastServerRef2(0, null, null, impl.checker); 111 112 Echo client = (Echo) ref.exportObject(impl, null, false); 113 114 int count = client.filterCount(obj); 115 System.out.printf("count: %d, obj: %s%n", count, obj); 116 Assert.assertEquals(count, expectedFilterCount, "wrong number of filter calls"); 117 } catch (RemoteException rex) { 118 if (expectedFilterCount == -1 && 119 UnmarshalException.class.equals(rex.getCause().getClass()) && 120 InvalidClassException.class.equals(rex.getCause().getCause().getClass())) { 121 return; // normal expected exception 122 } 123 rex.printStackTrace(); 124 Assert.fail("unexpected remote exception", rex); 125 } catch (Exception rex) { 126 Assert.fail("unexpected exception", rex); 127 } 128 } 129 130 /** 131 * A simple Serializable holding an object that is passed by value. 132 * It and its contents are checked by the filter. 133 */ 134 static class XX implements Serializable { 135 private static final long serialVersionUID = 362498820763181265L; 136 137 final Object obj; 138 XX(Object obj)139 XX(Object obj) { 140 this.obj = obj; 141 } 142 toString()143 public String toString() { 144 return super.toString() + "//" + Objects.toString(obj); 145 } 146 } 147 148 interface Echo extends Remote { filterCount(Object obj)149 int filterCount(Object obj) throws RemoteException; 150 } 151 152 /** 153 * This remote object just counts the calls to the serialFilter 154 * and returns it. The caller can check the number against 155 * what was expected for the object passed as an argument. 156 * A new RemoteImpl is used for each test so the count starts at zero again. 157 */ 158 static class RemoteImpl implements Echo { 159 160 private static final long serialVersionUID = 1L; 161 162 transient Checker checker; 163 create()164 static RemoteImpl create() throws RemoteException { 165 RemoteImpl impl = new RemoteImpl(new Checker()); 166 return impl; 167 } 168 RemoteImpl(Checker checker)169 private RemoteImpl(Checker checker) throws RemoteException { 170 this.checker = checker; 171 } 172 filterCount(Object obj)173 public int filterCount(Object obj) throws RemoteException { 174 return checker.count(); 175 } 176 177 } 178 179 /** 180 * A ObjectInputFilter that just counts when it is called. 181 */ 182 static class Checker implements ObjectInputFilter { 183 int count; 184 185 @Override checkInput(ObjectInputFilter.FilterInfo info)186 public Status checkInput(ObjectInputFilter.FilterInfo info) { 187 if (info.serialClass() == RejectME.class) { 188 return Status.REJECTED; 189 } 190 count++; 191 return Status.UNDECIDED; 192 } 193 count()194 public int count() { 195 return count; 196 } 197 } 198 199 /** 200 * A class to be rejected by the filter. 201 */ 202 static class RejectME implements Serializable { 203 private static final long serialVersionUID = 2L; 204 } 205 206 } 207