1 /* 2 * Copyright (c) 2016, 2018, 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.ObjectInputFilter; 26 import java.io.Serializable; 27 28 import java.rmi.Remote; 29 import java.rmi.RemoteException; 30 import java.rmi.UnmarshalException; 31 32 import java.util.Objects; 33 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 /* 44 * @test 45 * @modules java.rmi/sun.rmi.registry 46 * java.rmi/sun.rmi.server 47 * java.rmi/sun.rmi.transport 48 * java.rmi/sun.rmi.transport.tcp 49 * @run testng/othervm FilterUSRTest 50 * @summary Check objects exported with ObjectInputFilters via internal UnicastServerRef(2) 51 */ 52 public class FilterUSRTest { 53 54 /** 55 * Data to test serialFilter call counts. 56 * - name 57 * - Object 58 * - expected count of calls to checkInput. 59 * 60 * @return array of test data 61 */ 62 @DataProvider(name = "bindData") bindObjects()63 static Object[][] bindObjects() { 64 Object[][] data = { 65 {"SimpleString", "SimpleString", 0}, 66 {"String", new XX("now is the time"), 1}, 67 {"String[]", new XX(new String[3]), 3}, 68 {"Long[4]", new XX(new Long[4]), 3}, 69 {"RejectME", new XX(new RejectME()), -1}, 70 }; 71 return data; 72 } 73 74 /* 75 * Test exporting an object with a serialFilter using UnicastServerRef.exportObject(). 76 * Send some objects and check the number of calls to the serialFilter. 77 */ 78 @Test(dataProvider = "bindData") UnicastServerRef(String name, Object obj, int expectedFilterCount)79 public void UnicastServerRef(String name, Object obj, int expectedFilterCount) throws RemoteException { 80 try { 81 RemoteImpl impl = RemoteImpl.create(); 82 UnicastServerRef ref = new UnicastServerRef(new LiveRef(0), impl.checker); 83 84 Echo client = (Echo) ref.exportObject(impl, null, false); 85 86 int count = client.filterCount(obj); 87 System.out.printf("count: %d, obj: %s%n", count, obj); 88 Assert.assertEquals(count, expectedFilterCount, "wrong number of filter calls"); 89 } catch (RemoteException rex) { 90 if (expectedFilterCount == -1 && 91 UnmarshalException.class.equals(rex.getCause().getClass()) && 92 InvalidClassException.class.equals(rex.getCause().getCause().getClass())) { 93 return; // normal expected exception 94 } 95 rex.printStackTrace(); 96 Assert.fail("unexpected remote exception", rex); 97 } catch (Exception ex) { 98 Assert.fail("unexpected exception", ex); 99 } 100 } 101 102 /* 103 * Test exporting an object with a serialFilter using UnicastServerRef2.exportObject() 104 * with explicit (but null) SocketFactories. 105 * Send some objects and check the number of calls to the serialFilter. 106 */ 107 @Test(dataProvider = "bindData") UnicastServerRef2(String name, Object obj, int expectedFilterCount)108 public void UnicastServerRef2(String name, Object obj, int expectedFilterCount) throws RemoteException { 109 try { 110 RemoteImpl impl = RemoteImpl.create(); 111 UnicastServerRef2 ref = new UnicastServerRef2(0, null, null, impl.checker); 112 113 Echo client = (Echo) ref.exportObject(impl, null, false); 114 115 int count = client.filterCount(obj); 116 System.out.printf("count: %d, obj: %s%n", count, obj); 117 Assert.assertEquals(count, expectedFilterCount, "wrong number of filter calls"); 118 } catch (RemoteException rex) { 119 if (expectedFilterCount == -1 && 120 UnmarshalException.class.equals(rex.getCause().getClass()) && 121 InvalidClassException.class.equals(rex.getCause().getCause().getClass())) { 122 return; // normal expected exception 123 } 124 rex.printStackTrace(); 125 Assert.fail("unexpected remote exception", rex); 126 } catch (Exception rex) { 127 Assert.fail("unexpected exception", rex); 128 } 129 } 130 131 /** 132 * A simple Serializable holding an object that is passed by value. 133 * It and its contents are checked by the filter. 134 */ 135 static class XX implements Serializable { 136 private static final long serialVersionUID = 362498820763181265L; 137 138 final Object obj; 139 XX(Object obj)140 XX(Object obj) { 141 this.obj = obj; 142 } 143 toString()144 public String toString() { 145 return super.toString() + "//" + Objects.toString(obj); 146 } 147 } 148 149 interface Echo extends Remote { filterCount(Object obj)150 int filterCount(Object obj) throws RemoteException; 151 } 152 153 /** 154 * This remote object just counts the calls to the serialFilter 155 * and returns it. The caller can check the number against 156 * what was expected for the object passed as an argument. 157 * A new RemoteImpl is used for each test so the count starts at zero again. 158 */ 159 static class RemoteImpl implements Echo { 160 161 private static final long serialVersionUID = 1L; 162 163 transient Checker checker; 164 create()165 static RemoteImpl create() throws RemoteException { 166 RemoteImpl impl = new RemoteImpl(new Checker()); 167 return impl; 168 } 169 RemoteImpl(Checker checker)170 private RemoteImpl(Checker checker) throws RemoteException { 171 this.checker = checker; 172 } 173 filterCount(Object obj)174 public int filterCount(Object obj) throws RemoteException { 175 return checker.count(); 176 } 177 178 } 179 180 /** 181 * A ObjectInputFilter that just counts when it is called. 182 */ 183 static class Checker implements ObjectInputFilter { 184 int count; 185 186 @Override checkInput(ObjectInputFilter.FilterInfo info)187 public Status checkInput(ObjectInputFilter.FilterInfo info) { 188 if (info.serialClass() == RejectME.class) { 189 return Status.REJECTED; 190 } 191 count++; 192 return Status.UNDECIDED; 193 } 194 count()195 public int count() { 196 return count; 197 } 198 } 199 200 /** 201 * A class to be rejected by the filter. 202 */ 203 static class RejectME implements Serializable { 204 private static final long serialVersionUID = 2L; 205 } 206 207 } 208