From 19a7f64e31129643dfef0d6640b0a41daee8c16d Mon Sep 17 00:00:00 2001 From: xiaohuang09 Date: Thu, 31 Aug 2023 13:55:11 +0800 Subject: [PATCH] add patch --- hessian-20230907.patch | 6985 ++++++++++++++++++++++++++++++++++++++++ hessian-4.0.65.pom | 5 + hessian.spec | 16 +- 3 files changed, 7002 insertions(+), 4 deletions(-) create mode 100644 hessian-20230907.patch diff --git a/hessian-20230907.patch b/hessian-20230907.patch new file mode 100644 index 0000000..026bece --- /dev/null +++ b/hessian-20230907.patch @@ -0,0 +1,6985 @@ +diff -Npur hessian-4.0.65-src/META-INF/hessian/deserializers hessian-4.0.65-fix/META-INF/hessian/deserializers +--- hessian-4.0.65-src/META-INF/hessian/deserializers 1970-01-01 08:00:00.000000000 +0800 ++++ hessian-4.0.65-fix/META-INF/hessian/deserializers 2023-08-15 18:39:22.000000000 +0800 +@@ -0,0 +1,3 @@ ++java.io.File=com.caucho.hessian.io.FileDeserializer ++java.math.BigDecimal=com.caucho.hessian.io.BigDecimalDeserializer ++javax.management.ObjectName=com.caucho.hessian.io.ObjectNameDeserializer +diff -Npur hessian-4.0.65-src/META-INF/hessian/serializers hessian-4.0.65-fix/META-INF/hessian/serializers +--- hessian-4.0.65-src/META-INF/hessian/serializers 1970-01-01 08:00:00.000000000 +0800 ++++ hessian-4.0.65-fix/META-INF/hessian/serializers 2023-08-15 18:39:22.000000000 +0800 +@@ -0,0 +1,6 @@ ++com.caucho.hessian.io.HessianRemoteObject=com.caucho.hessian.io.RemoteSerializer ++com.caucho.burlap.io.BurlapRemoteObject=com.caucho.hessian.io.RemoteSerializer ++java.io.File=com.caucho.hessian.io.StringValueSerializer ++java.math.BigDecimal=com.caucho.hessian.io.StringValueSerializer ++java.util.Locale=com.caucho.hessian.io.LocaleSerializer ++javax.management.ObjectName=com.caucho.hessian.io.StringValueSerializer +diff -Npur hessian-4.0.65-src/com/caucho/hessian/client/HessianProxy.java hessian-4.0.65-fix/com/caucho/hessian/client/HessianProxy.java +--- hessian-4.0.65-src/com/caucho/hessian/client/HessianProxy.java 2020-07-23 12:51:28.000000000 +0800 ++++ hessian-4.0.65-fix/com/caucho/hessian/client/HessianProxy.java 2023-08-15 18:39:22.000000000 +0800 +@@ -1,483 +1,483 @@ +-/* +- * The Apache Software License, Version 1.1 +- * +- * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions +- * are met: +- * +- * 1. Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * +- * 2. Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in +- * the documentation and/or other materials provided with the +- * distribution. +- * +- * 3. The end-user documentation included with the redistribution, if +- * any, must include the following acknowlegement: +- * "This product includes software developed by the +- * Caucho Technology (http://www.caucho.com/)." +- * Alternately, this acknowlegement may appear in the software itself, +- * if and wherever such third-party acknowlegements normally appear. +- * +- * 4. The names "Hessian", "Resin", and "Caucho" must not be used to +- * endorse or promote products derived from this software without prior +- * written permission. For written permission, please contact +- * info@caucho.com. +- * +- * 5. Products derived from this software may not be called "Resin" +- * nor may "Resin" appear in their names without prior written +- * permission of Caucho Technology. +- * +- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +- * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS +- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +- * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- * +- * @author Scott Ferguson +- */ +- +-package com.caucho.hessian.client; +- +-import com.caucho.hessian.io.*; +-import com.caucho.services.server.*; +- +-import java.io.*; +-import java.util.logging.*; +-import java.lang.reflect.InvocationHandler; +-import java.lang.reflect.Method; +-import java.lang.reflect.Proxy; +-import java.util.WeakHashMap; +-import java.net.HttpURLConnection; +-import java.net.URL; +-import java.net.URLConnection; +-import java.util.zip.*; +- +-/** +- * Proxy implementation for Hessian clients. Applications will generally +- * use HessianProxyFactory to create proxy clients. +- */ +-public class HessianProxy implements InvocationHandler, Serializable { +- private static final Logger log +- = Logger.getLogger(HessianProxy.class.getName()); +- +- protected HessianProxyFactory _factory; +- +- private WeakHashMap _mangleMap +- = new WeakHashMap(); +- +- private Class _type; +- private URL _url; +- +- /** +- * Protected constructor for subclassing +- */ +- protected HessianProxy(URL url, HessianProxyFactory factory) +- { +- this(url, factory, null); +- } +- +- /** +- * Protected constructor for subclassing +- */ +- protected HessianProxy(URL url, +- HessianProxyFactory factory, +- Class type) +- { +- _factory = factory; +- _url = url; +- _type = type; +- } +- +- /** +- * Returns the proxy's URL. +- */ +- public URL getURL() +- { +- return _url; +- } +- +- /** +- * Handles the object invocation. +- * +- * @param proxy the proxy object to invoke +- * @param method the method to call +- * @param args the arguments to the proxy object +- */ +- public Object invoke(Object proxy, Method method, Object []args) +- throws Throwable +- { +- String mangleName; +- +- synchronized (_mangleMap) { +- mangleName = _mangleMap.get(method); +- } +- +- if (mangleName == null) { +- String methodName = method.getName(); +- Class []params = method.getParameterTypes(); +- +- // equals and hashCode are special cased +- if (methodName.equals("equals") +- && params.length == 1 && params[0].equals(Object.class)) { +- Object value = args[0]; +- if (value == null || ! Proxy.isProxyClass(value.getClass())) +- return Boolean.FALSE; +- +- Object proxyHandler = Proxy.getInvocationHandler(value); +- +- if (! (proxyHandler instanceof HessianProxy)) +- return Boolean.FALSE; +- +- HessianProxy handler = (HessianProxy) proxyHandler; +- +- return new Boolean(_url.equals(handler.getURL())); +- } +- else if (methodName.equals("hashCode") && params.length == 0) +- return new Integer(_url.hashCode()); +- else if (methodName.equals("getHessianType")) +- return proxy.getClass().getInterfaces()[0].getName(); +- else if (methodName.equals("getHessianURL")) +- return _url.toString(); +- else if (methodName.equals("toString") && params.length == 0) +- return "HessianProxy[" + _url + "]"; +- +- if (! _factory.isOverloadEnabled()) +- mangleName = method.getName(); +- else +- mangleName = mangleName(method); +- +- synchronized (_mangleMap) { +- _mangleMap.put(method, mangleName); +- } +- } +- +- InputStream is = null; +- HessianConnection conn = null; +- +- try { +- if (log.isLoggable(Level.FINER)) +- log.finer("Hessian[" + _url + "] calling " + mangleName); +- +- conn = sendRequest(mangleName, args); +- +- is = getInputStream(conn); +- +- if (log.isLoggable(Level.FINEST)) { +- PrintWriter dbg = new PrintWriter(new LogWriter(log)); +- HessianDebugInputStream dIs +- = new HessianDebugInputStream(is, dbg); +- +- dIs.startTop2(); +- +- is = dIs; +- } +- +- AbstractHessianInput in; +- +- int code = is.read(); +- +- if (code == 'H') { +- int major = is.read(); +- int minor = is.read(); +- +- in = _factory.getHessian2Input(is); +- +- Object value = in.readReply(method.getReturnType()); +- +- if (value instanceof InputStream) { +- value = new ResultInputStream(conn, is, in, (InputStream) value); +- is = null; +- conn = null; +- } +- +- return value; +- } +- else if (code == 'r') { +- int major = is.read(); +- int minor = is.read(); +- +- in = _factory.getHessianInput(is); +- +- in.startReplyBody(); +- +- Object value = in.readObject(method.getReturnType()); +- +- if (value instanceof InputStream) { +- value = new ResultInputStream(conn, is, in, (InputStream) value); +- is = null; +- conn = null; +- } +- else { +- in.completeReply(); +- } +- +- return value; +- } +- else +- throw new HessianProtocolException("'" + (char) code + "' is an unknown code"); +- } catch (HessianProtocolException e) { +- throw new HessianRuntimeException(e); +- } finally { +- try { +- if (is != null) +- is.close(); +- } catch (Exception e) { +- log.log(Level.FINE, e.toString(), e); +- } +- +- try { +- if (conn != null) +- conn.destroy(); +- } catch (Exception e) { +- log.log(Level.FINE, e.toString(), e); +- } +- } +- } +- +- protected InputStream getInputStream(HessianConnection conn) +- throws IOException +- { +- InputStream is = conn.getInputStream(); +- +- if ("deflate".equals(conn.getContentEncoding())) { +- is = new InflaterInputStream(is, new Inflater(true)); +- } +- +- return is; +- } +- +- protected String mangleName(Method method) +- { +- Class []param = method.getParameterTypes(); +- +- if (param == null || param.length == 0) +- return method.getName(); +- else +- return AbstractSkeleton.mangleName(method, false); +- } +- +- /** +- * Sends the HTTP request to the Hessian connection. +- */ +- protected HessianConnection sendRequest(String methodName, Object []args) +- throws IOException +- { +- HessianConnection conn = null; +- +- conn = _factory.getConnectionFactory().open(_url); +- boolean isValid = false; +- +- try { +- addRequestHeaders(conn); +- +- OutputStream os = null; +- +- try { +- os = conn.getOutputStream(); +- } catch (Exception e) { +- throw new HessianRuntimeException(e); +- } +- +- if (log.isLoggable(Level.FINEST)) { +- PrintWriter dbg = new PrintWriter(new LogWriter(log)); +- HessianDebugOutputStream dOs = new HessianDebugOutputStream(os, dbg); +- dOs.startTop2(); +- os = dOs; +- } +- +- AbstractHessianOutput out = _factory.getHessianOutput(os); +- +- out.call(methodName, args); +- out.flush(); +- +- conn.sendRequest(); +- +- isValid = true; +- +- return conn; +- } finally { +- if (! isValid && conn != null) +- conn.destroy(); +- } +- } +- +- /** +- * Method that allows subclasses to add request headers such as cookies. +- * Default implementation is empty. +- */ +- protected void addRequestHeaders(HessianConnection conn) +- { +- conn.addHeader("Content-Type", "x-application/hessian"); +- conn.addHeader("Accept-Encoding", "deflate"); +- +- String basicAuth = _factory.getBasicAuth(); +- +- if (basicAuth != null) +- conn.addHeader("Authorization", basicAuth); +- } +- +- /** +- * Method that allows subclasses to parse response headers such as cookies. +- * Default implementation is empty. +- * @param conn +- */ +- protected void parseResponseHeaders(URLConnection conn) +- { +- } +- +- public Object writeReplace() +- { +- return new HessianRemote(_type.getName(), _url.toString()); +- } +- +- static class ResultInputStream extends InputStream { +- private HessianConnection _conn; +- private InputStream _connIs; +- private AbstractHessianInput _in; +- private InputStream _hessianIs; +- +- ResultInputStream(HessianConnection conn, +- InputStream is, +- AbstractHessianInput in, +- InputStream hessianIs) +- { +- _conn = conn; +- _connIs = is; +- _in = in; +- _hessianIs = hessianIs; +- } +- +- public int read() +- throws IOException +- { +- if (_hessianIs != null) { +- int value = _hessianIs.read(); +- +- if (value < 0) +- close(); +- +- return value; +- } +- else +- return -1; +- } +- +- public int read(byte []buffer, int offset, int length) +- throws IOException +- { +- if (_hessianIs != null) { +- int value = _hessianIs.read(buffer, offset, length); +- +- if (value < 0) +- close(); +- +- return value; +- } +- else +- return -1; +- } +- +- public void close() +- throws IOException +- { +- HessianConnection conn = _conn; +- _conn = null; +- +- InputStream connIs = _connIs; +- _connIs = null; +- +- AbstractHessianInput in = _in; +- _in = null; +- +- InputStream hessianIs = _hessianIs; +- _hessianIs = null; +- +- try { +- if (hessianIs != null) +- hessianIs.close(); +- } catch (Exception e) { +- log.log(Level.FINE, e.toString(), e); +- } +- +- try { +- if (in != null) { +- in.completeReply(); +- in.close(); +- } +- } catch (Exception e) { +- log.log(Level.FINE, e.toString(), e); +- } +- +- try { +- if (connIs != null) { +- connIs.close(); +- } +- } catch (Exception e) { +- log.log(Level.FINE, e.toString(), e); +- } +- +- try { +- if (conn != null) { +- conn.close(); +- } +- } catch (Exception e) { +- log.log(Level.FINE, e.toString(), e); +- } +- } +- } +- +- static class LogWriter extends Writer { +- private Logger _log; +- private Level _level = Level.FINEST; +- private StringBuilder _sb = new StringBuilder(); +- +- LogWriter(Logger log) +- { +- _log = log; +- } +- +- public void write(char ch) +- { +- if (ch == '\n' && _sb.length() > 0) { +- _log.fine(_sb.toString()); +- _sb.setLength(0); +- } +- else +- _sb.append((char) ch); +- } +- +- public void write(char []buffer, int offset, int length) +- { +- for (int i = 0; i < length; i++) { +- char ch = buffer[offset + i]; +- +- if (ch == '\n' && _sb.length() > 0) { +- _log.log(_level, _sb.toString()); +- _sb.setLength(0); +- } +- else +- _sb.append((char) ch); +- } +- } +- +- public void flush() +- { +- } +- +- public void close() +- { +- if (_sb.length() > 0) +- _log.log(_level, _sb.toString()); +- } +- } +-} ++/* ++ * The Apache Software License, Version 1.1 ++ * ++ * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * 3. The end-user documentation included with the redistribution, if ++ * any, must include the following acknowlegement: ++ * "This product includes software developed by the ++ * Caucho Technology (http://www.caucho.com/)." ++ * Alternately, this acknowlegement may appear in the software itself, ++ * if and wherever such third-party acknowlegements normally appear. ++ * ++ * 4. The names "Hessian", "Resin", and "Caucho" must not be used to ++ * endorse or promote products derived from this software without prior ++ * written permission. For written permission, please contact ++ * info@caucho.com. ++ * ++ * 5. Products derived from this software may not be called "Resin" ++ * nor may "Resin" appear in their names without prior written ++ * permission of Caucho Technology. ++ * ++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED ++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++ * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS ++ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, ++ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT ++ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ++ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE ++ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN ++ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * @author Scott Ferguson ++ */ ++ ++package com.caucho.hessian.client; ++ ++import com.caucho.hessian.io.*; ++import com.caucho.services.server.*; ++ ++import java.io.*; ++import java.util.logging.*; ++import java.lang.reflect.InvocationHandler; ++import java.lang.reflect.Method; ++import java.lang.reflect.Proxy; ++import java.util.WeakHashMap; ++import java.net.HttpURLConnection; ++import java.net.URL; ++import java.net.URLConnection; ++import java.util.zip.*; ++ ++/** ++ * Proxy implementation for Hessian clients. Applications will generally ++ * use HessianProxyFactory to create proxy clients. ++ */ ++public class HessianProxy implements InvocationHandler, Serializable { ++ private static final Logger log ++ = Logger.getLogger(HessianProxy.class.getName()); ++ ++ protected HessianProxyFactory _factory; ++ ++ private WeakHashMap _mangleMap ++ = new WeakHashMap(); ++ ++ private Class _type; ++ private URL _url; ++ ++ /** ++ * Protected constructor for subclassing ++ */ ++ protected HessianProxy(URL url, HessianProxyFactory factory) ++ { ++ this(url, factory, null); ++ } ++ ++ /** ++ * Protected constructor for subclassing ++ */ ++ protected HessianProxy(URL url, ++ HessianProxyFactory factory, ++ Class type) ++ { ++ _factory = factory; ++ _url = url; ++ _type = type; ++ } ++ ++ /** ++ * Returns the proxy's URL. ++ */ ++ public URL getURL() ++ { ++ return _url; ++ } ++ ++ /** ++ * Handles the object invocation. ++ * ++ * @param proxy the proxy object to invoke ++ * @param method the method to call ++ * @param args the arguments to the proxy object ++ */ ++ public Object invoke(Object proxy, Method method, Object []args) ++ throws Throwable ++ { ++ String mangleName; ++ ++ synchronized (_mangleMap) { ++ mangleName = _mangleMap.get(method); ++ } ++ ++ if (mangleName == null) { ++ String methodName = method.getName(); ++ Class []params = method.getParameterTypes(); ++ ++ // equals and hashCode are special cased ++ if (methodName.equals("equals") ++ && params.length == 1 && params[0].equals(Object.class)) { ++ Object value = args[0]; ++ if (value == null || ! Proxy.isProxyClass(value.getClass())) ++ return Boolean.FALSE; ++ ++ Object proxyHandler = Proxy.getInvocationHandler(value); ++ ++ if (! (proxyHandler instanceof HessianProxy)) ++ return Boolean.FALSE; ++ ++ HessianProxy handler = (HessianProxy) proxyHandler; ++ ++ return new Boolean(_url.equals(handler.getURL())); ++ } ++ else if (methodName.equals("hashCode") && params.length == 0) ++ return new Integer(_url.hashCode()); ++ else if (methodName.equals("getHessianType")) ++ return proxy.getClass().getInterfaces()[0].getName(); ++ else if (methodName.equals("getHessianURL")) ++ return _url.toString(); ++ else if (methodName.equals("toString") && params.length == 0) ++ return "HessianProxy[" + _url + "]"; ++ ++ if (! _factory.isOverloadEnabled()) ++ mangleName = method.getName(); ++ else ++ mangleName = mangleName(method); ++ ++ synchronized (_mangleMap) { ++ _mangleMap.put(method, mangleName); ++ } ++ } ++ ++ InputStream is = null; ++ HessianConnection conn = null; ++ ++ try { ++ if (log.isLoggable(Level.FINER)) ++ log.finer("Hessian[" + _url + "] calling " + mangleName); ++ ++ conn = sendRequest(mangleName, args); ++ ++ is = getInputStream(conn); ++ ++ if (log.isLoggable(Level.FINEST)) { ++ PrintWriter dbg = new PrintWriter(new LogWriter(log)); ++ HessianDebugInputStream dIs ++ = new HessianDebugInputStream(is, dbg); ++ ++ dIs.startTop2(); ++ ++ is = dIs; ++ } ++ ++ AbstractHessianInput in; ++ ++ int code = is.read(); ++ ++ if (code == 'H') { ++ int major = is.read(); ++ int minor = is.read(); ++ ++ in = _factory.getHessian2Input(is); ++ ++ Object value = in.readReply(method.getReturnType()); ++ ++ if (value instanceof InputStream) { ++ value = new ResultInputStream(conn, is, in, (InputStream) value); ++ is = null; ++ conn = null; ++ } ++ ++ return value; ++ } ++ else if (code == 'r') { ++ int major = is.read(); ++ int minor = is.read(); ++ ++ in = _factory.getHessianInput(is); ++ ++ in.startReplyBody(); ++ ++ Object value = in.readObject(method.getReturnType()); ++ ++ if (value instanceof InputStream) { ++ value = new ResultInputStream(conn, is, in, (InputStream) value); ++ is = null; ++ conn = null; ++ } ++ else { ++ in.completeReply(); ++ } ++ ++ return value; ++ } ++ else ++ throw new HessianProtocolException("'" + (char) code + "' is an unknown code"); ++ } catch (HessianProtocolException e) { ++ throw new HessianRuntimeException(e); ++ } finally { ++ try { ++ if (is != null) ++ is.close(); ++ } catch (Exception e) { ++ log.log(Level.FINE, e.toString(), e); ++ } ++ ++ try { ++ if (conn != null) ++ conn.destroy(); ++ } catch (Exception e) { ++ log.log(Level.FINE, e.toString(), e); ++ } ++ } ++ } ++ ++ protected InputStream getInputStream(HessianConnection conn) ++ throws IOException ++ { ++ InputStream is = conn.getInputStream(); ++ ++ if ("deflate".equals(conn.getContentEncoding())) { ++ is = new InflaterInputStream(is, new Inflater(true)); ++ } ++ ++ return is; ++ } ++ ++ protected String mangleName(Method method) ++ { ++ Class []param = method.getParameterTypes(); ++ ++ if (param == null || param.length == 0) ++ return method.getName(); ++ else ++ return AbstractSkeleton.mangleName(method, false); ++ } ++ ++ /** ++ * Sends the HTTP request to the Hessian connection. ++ */ ++ protected HessianConnection sendRequest(String methodName, Object []args) ++ throws IOException ++ { ++ HessianConnection conn = null; ++ ++ conn = _factory.getConnectionFactory().open(_url); ++ boolean isValid = false; ++ ++ try { ++ addRequestHeaders(conn); ++ ++ OutputStream os = null; ++ ++ try { ++ os = conn.getOutputStream(); ++ } catch (Exception e) { ++ throw new HessianRuntimeException(e); ++ } ++ ++ if (log.isLoggable(Level.FINEST)) { ++ PrintWriter dbg = new PrintWriter(new LogWriter(log)); ++ HessianDebugOutputStream dOs = new HessianDebugOutputStream(os, dbg); ++ dOs.startTop2(); ++ os = dOs; ++ } ++ ++ AbstractHessianOutput out = _factory.getHessianOutput(os); ++ ++ out.call(methodName, args); ++ out.flush(); ++ ++ conn.sendRequest(); ++ ++ isValid = true; ++ ++ return conn; ++ } finally { ++ if (! isValid && conn != null) ++ conn.destroy(); ++ } ++ } ++ ++ /** ++ * Method that allows subclasses to add request headers such as cookies. ++ * Default implementation is empty. ++ */ ++ protected void addRequestHeaders(HessianConnection conn) ++ { ++ conn.addHeader("Content-Type", "x-application/hessian"); ++ conn.addHeader("Interface-Name", this._type.getCanonicalName()); ++ ++ String basicAuth = _factory.getBasicAuth(); ++ ++ if (basicAuth != null) ++ conn.addHeader("Authorization", basicAuth); ++ } ++ ++ /** ++ * Method that allows subclasses to parse response headers such as cookies. ++ * Default implementation is empty. ++ * @param conn ++ */ ++ protected void parseResponseHeaders(URLConnection conn) ++ { ++ } ++ ++ public Object writeReplace() ++ { ++ return new HessianRemote(_type.getName(), _url.toString()); ++ } ++ ++ static class ResultInputStream extends InputStream { ++ private HessianConnection _conn; ++ private InputStream _connIs; ++ private AbstractHessianInput _in; ++ private InputStream _hessianIs; ++ ++ ResultInputStream(HessianConnection conn, ++ InputStream is, ++ AbstractHessianInput in, ++ InputStream hessianIs) ++ { ++ _conn = conn; ++ _connIs = is; ++ _in = in; ++ _hessianIs = hessianIs; ++ } ++ ++ public int read() ++ throws IOException ++ { ++ if (_hessianIs != null) { ++ int value = _hessianIs.read(); ++ ++ if (value < 0) ++ close(); ++ ++ return value; ++ } ++ else ++ return -1; ++ } ++ ++ public int read(byte []buffer, int offset, int length) ++ throws IOException ++ { ++ if (_hessianIs != null) { ++ int value = _hessianIs.read(buffer, offset, length); ++ ++ if (value < 0) ++ close(); ++ ++ return value; ++ } ++ else ++ return -1; ++ } ++ ++ public void close() ++ throws IOException ++ { ++ HessianConnection conn = _conn; ++ _conn = null; ++ ++ InputStream connIs = _connIs; ++ _connIs = null; ++ ++ AbstractHessianInput in = _in; ++ _in = null; ++ ++ InputStream hessianIs = _hessianIs; ++ _hessianIs = null; ++ ++ try { ++ if (hessianIs != null) ++ hessianIs.close(); ++ } catch (Exception e) { ++ log.log(Level.FINE, e.toString(), e); ++ } ++ ++ try { ++ if (in != null) { ++ in.completeReply(); ++ in.close(); ++ } ++ } catch (Exception e) { ++ log.log(Level.FINE, e.toString(), e); ++ } ++ ++ try { ++ if (connIs != null) { ++ connIs.close(); ++ } ++ } catch (Exception e) { ++ log.log(Level.FINE, e.toString(), e); ++ } ++ ++ try { ++ if (conn != null) { ++ conn.close(); ++ } ++ } catch (Exception e) { ++ log.log(Level.FINE, e.toString(), e); ++ } ++ } ++ } ++ ++ static class LogWriter extends Writer { ++ private Logger _log; ++ private Level _level = Level.FINEST; ++ private StringBuilder _sb = new StringBuilder(); ++ ++ LogWriter(Logger log) ++ { ++ _log = log; ++ } ++ ++ public void write(char ch) ++ { ++ if (ch == '\n' && _sb.length() > 0) { ++ _log.fine(_sb.toString()); ++ _sb.setLength(0); ++ } ++ else ++ _sb.append((char) ch); ++ } ++ ++ public void write(char []buffer, int offset, int length) ++ { ++ for (int i = 0; i < length; i++) { ++ char ch = buffer[offset + i]; ++ ++ if (ch == '\n' && _sb.length() > 0) { ++ _log.log(_level, _sb.toString()); ++ _sb.setLength(0); ++ } ++ else ++ _sb.append((char) ch); ++ } ++ } ++ ++ public void flush() ++ { ++ } ++ ++ public void close() ++ { ++ if (_sb.length() > 0) ++ _log.log(_level, _sb.toString()); ++ } ++ } ++} +diff -Npur hessian-4.0.65-src/com/caucho/hessian/io/ContextSerializerFactory.java hessian-4.0.65-fix/com/caucho/hessian/io/ContextSerializerFactory.java +--- hessian-4.0.65-src/com/caucho/hessian/io/ContextSerializerFactory.java 2020-07-23 12:51:28.000000000 +0800 ++++ hessian-4.0.65-fix/com/caucho/hessian/io/ContextSerializerFactory.java 2023-08-15 18:39:22.000000000 +0800 +@@ -1,507 +1,519 @@ +-/* +- * Copyright (c) 2001-2008 Caucho Technology, Inc. All rights reserved. +- * +- * The Apache Software License, Version 1.1 +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions +- * are met: +- * +- * 1. Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * +- * 2. Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in +- * the documentation and/or other materials provided with the +- * distribution. +- * +- * 3. The end-user documentation included with the redistribution, if +- * any, must include the following acknowlegement: +- * "This product includes software developed by the +- * Caucho Technology (http://www.caucho.com/)." +- * Alternately, this acknowlegement may appear in the software itself, +- * if and wherever such third-party acknowlegements normally appear. +- * +- * 4. The names "Burlap", "Resin", and "Caucho" must not be used to +- * endorse or promote products derived from this software without prior +- * written permission. For written permission, please contact +- * info@caucho.com. +- * +- * 5. Products derived from this software may not be called "Resin" +- * nor may "Resin" appear in their names without prior written +- * permission of Caucho Technology. +- * +- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +- * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS +- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +- * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- * +- * @author Scott Ferguson +- */ +- +-package com.caucho.hessian.io; +- +-import java.io.InputStream; +-import java.lang.ref.SoftReference; +-import java.lang.ref.WeakReference; +-import java.net.InetAddress; +-import java.net.URL; +-import java.util.Enumeration; +-import java.util.HashMap; +-import java.util.HashSet; +-import java.util.Map; +-import java.util.Properties; +-import java.util.WeakHashMap; +-import java.util.concurrent.ConcurrentHashMap; +-import java.util.logging.Level; +-import java.util.logging.Logger; +- +-import com.caucho.hessian.HessianException; +- +-/** +- * The classloader-specific Factory for returning serialization +- */ +-public class ContextSerializerFactory +-{ +- private static final Logger log +- = Logger.getLogger(ContextSerializerFactory.class.getName()); +- +- private static Deserializer OBJECT_DESERIALIZER +- = new BasicDeserializer(BasicDeserializer.OBJECT); +- +- private static final WeakHashMap> +- _contextRefMap +- = new WeakHashMap>(); +- +- private static final ClassLoader _systemClassLoader; +- +- private static HashMap _staticSerializerMap; +- private static HashMap _staticDeserializerMap; +- private static HashMap _staticClassNameMap; +- +- private ContextSerializerFactory _parent; +- private WeakReference _loaderRef; +- +- private final HashSet _serializerFiles = new HashSet(); +- private final HashSet _deserializerFiles = new HashSet(); +- +- private final HashMap _serializerClassMap +- = new HashMap(); +- +- private final ConcurrentHashMap _customSerializerMap +- = new ConcurrentHashMap(); +- +- private final HashMap,Serializer> _serializerInterfaceMap +- = new HashMap,Serializer>(); +- +- private final HashMap _deserializerClassMap +- = new HashMap(); +- +- private final HashMap _deserializerClassNameMap +- = new HashMap(); +- +- private final ConcurrentHashMap _customDeserializerMap +- = new ConcurrentHashMap(); +- +- private final HashMap,Deserializer> _deserializerInterfaceMap +- = new HashMap,Deserializer>(); +- +- public ContextSerializerFactory(ContextSerializerFactory parent, +- ClassLoader loader) +- { +- if (loader == null) +- loader = _systemClassLoader; +- +- _loaderRef = new WeakReference(loader); +- +- init(); +- } +- +- public static ContextSerializerFactory create() +- { +- return create(Thread.currentThread().getContextClassLoader()); +- } +- +- public static ContextSerializerFactory create(ClassLoader loader) +- { +- synchronized (_contextRefMap) { +- SoftReference factoryRef +- = _contextRefMap.get(loader); +- +- ContextSerializerFactory factory = null; +- +- if (factoryRef != null) +- factory = factoryRef.get(); +- +- if (factory == null) { +- ContextSerializerFactory parent = null; +- +- if (loader != null) +- parent = create(loader.getParent()); +- +- factory = new ContextSerializerFactory(parent, loader); +- factoryRef = new SoftReference(factory); +- +- _contextRefMap.put(loader, factoryRef); +- } +- +- return factory; +- } +- } +- +- public ClassLoader getClassLoader() +- { +- WeakReference loaderRef = _loaderRef; +- +- if (loaderRef != null) +- return loaderRef.get(); +- else +- return null; +- } +- +- /** +- * Returns the serializer for a given class. +- */ +- public Serializer getSerializer(String className) +- { +- Serializer serializer = _serializerClassMap.get(className); +- +- if (serializer == AbstractSerializer.NULL) +- return null; +- else +- return serializer; +- } +- +- /** +- * Returns a custom serializer the class +- * +- * @param cl the class of the object that needs to be serialized. +- * +- * @return a serializer object for the serialization. +- */ +- public Serializer getCustomSerializer(Class cl) +- { +- Serializer serializer = _customSerializerMap.get(cl.getName()); +- +- if (serializer == AbstractSerializer.NULL) +- return null; +- else if (serializer != null) +- return serializer; +- +- try { +- Class serClass = Class.forName(cl.getName() + "HessianSerializer", +- false, cl.getClassLoader()); +- +- Serializer ser = (Serializer) serClass.newInstance(); +- +- _customSerializerMap.put(cl.getName(), ser); +- +- return ser; +- } catch (ClassNotFoundException e) { +- log.log(Level.ALL, e.toString(), e); +- } catch (Exception e) { +- throw new HessianException(e); +- } +- +- _customSerializerMap.put(cl.getName(), AbstractSerializer.NULL); +- +- return null; +- } +- +- /** +- * Returns the deserializer for a given class. +- */ +- public Deserializer getDeserializer(String className) +- { +- Deserializer deserializer = _deserializerClassMap.get(className); +- +- if (deserializer != null && deserializer != AbstractDeserializer.NULL) { +- return deserializer; +- } +- +- deserializer = _deserializerInterfaceMap.get(className); +- +- if (deserializer != null && deserializer != AbstractDeserializer.NULL) { +- return deserializer; +- } +- +- return null; +- } +- +- /** +- * Returns a custom deserializer the class +- * +- * @param cl the class of the object that needs to be deserialized. +- * +- * @return a deserializer object for the deserialization. +- */ +- public Deserializer getCustomDeserializer(Class cl) +- { +- Deserializer deserializer = _customDeserializerMap.get(cl.getName()); +- +- if (deserializer == AbstractDeserializer.NULL) +- return null; +- else if (deserializer != null) +- return deserializer; +- +- try { +- Class serClass = Class.forName(cl.getName() + "HessianDeserializer", +- false, cl.getClassLoader()); +- +- Deserializer ser = (Deserializer) serClass.newInstance(); +- +- _customDeserializerMap.put(cl.getName(), ser); +- +- return ser; +- } catch (ClassNotFoundException e) { +- log.log(Level.ALL, e.toString(), e); +- } catch (Exception e) { +- throw new HessianException(e); +- } +- +- _customDeserializerMap.put(cl.getName(), AbstractDeserializer.NULL); +- +- return null; +- } +- +- /** +- * Initialize the factory +- */ +- private void init() +- { +- if (_parent != null) { +- _serializerFiles.addAll(_parent._serializerFiles); +- _deserializerFiles.addAll(_parent._deserializerFiles); +- +- _serializerClassMap.putAll(_parent._serializerClassMap); +- _deserializerClassMap.putAll(_parent._deserializerClassMap); +- } +- +- if (_parent == null) { +- _serializerClassMap.putAll(_staticSerializerMap); +- _deserializerClassMap.putAll(_staticDeserializerMap); +- _deserializerClassNameMap.putAll(_staticClassNameMap); +- } +- +- HashMap classMap; +- +- classMap = new HashMap(); +- initSerializerFiles("META-INF/hessian/serializers", +- _serializerFiles, +- classMap, +- Serializer.class); +- +- for (Map.Entry entry : classMap.entrySet()) { +- try { +- Serializer ser = (Serializer) entry.getValue().newInstance(); +- +- if (entry.getKey().isInterface()) +- _serializerInterfaceMap.put(entry.getKey(), ser); +- else +- _serializerClassMap.put(entry.getKey().getName(), ser); +- } catch (Exception e) { +- throw new HessianException(e); +- } +- } +- +- classMap = new HashMap(); +- initSerializerFiles("META-INF/hessian/deserializers", +- _deserializerFiles, +- classMap, +- Deserializer.class); +- +- for (Map.Entry entry : classMap.entrySet()) { +- try { +- Deserializer ser = (Deserializer) entry.getValue().newInstance(); +- +- if (entry.getKey().isInterface()) +- _deserializerInterfaceMap.put(entry.getKey(), ser); +- else { +- _deserializerClassMap.put(entry.getKey().getName(), ser); +- } +- } catch (Exception e) { +- throw new HessianException(e); +- } +- } +- } +- +- private void initSerializerFiles(String fileName, +- HashSet fileList, +- HashMap classMap, +- Class type) +- { +- try { +- ClassLoader classLoader = getClassLoader(); +- +- // on systems with the security manager enabled, the system classloader +- // is null +- if (classLoader == null) +- return; +- +- Enumeration iter; +- +- iter = classLoader.getResources(fileName); +- while (iter.hasMoreElements()) { +- URL url = (URL) iter.nextElement(); +- +- if (fileList.contains(url.toString())) +- continue; +- +- fileList.add(url.toString()); +- +- InputStream is = null; +- try { +- is = url.openStream(); +- +- Properties props = new Properties(); +- props.load(is); +- +- for (Map.Entry entry : props.entrySet()) { +- String apiName = (String) entry.getKey(); +- String serializerName = (String) entry.getValue(); +- +- Class apiClass = null; +- Class serializerClass = null; +- +- try { +- apiClass = Class.forName(apiName, false, classLoader); +- } catch (ClassNotFoundException e) { +- log.fine(url + ": " + apiName + " is not available in this context: " + getClassLoader()); +- continue; +- } +- +- try { +- serializerClass = Class.forName(serializerName, false, classLoader); +- } catch (ClassNotFoundException e) { +- log.fine(url + ": " + serializerName + " is not available in this context: " + getClassLoader()); +- continue; +- } +- +- if (! type.isAssignableFrom(serializerClass)) +- throw new HessianException(url + ": " + serializerClass.getName() + " is invalid because it does not implement " + type.getName()); +- +- classMap.put(apiClass, serializerClass); +- } +- } finally { +- if (is != null) +- is.close(); +- } +- } +- } catch (RuntimeException e) { +- throw e; +- } catch (Exception e) { +- throw new HessianException(e); +- } +- } +- +- private static void addBasic(Class cl, String typeName, int type) +- { +- _staticSerializerMap.put(cl.getName(), new BasicSerializer(type)); +- +- Deserializer deserializer = new BasicDeserializer(type); +- _staticDeserializerMap.put(cl.getName(), deserializer); +- _staticClassNameMap.put(typeName, deserializer); +- } +- +- static { +- _staticSerializerMap = new HashMap(); +- _staticDeserializerMap = new HashMap(); +- _staticClassNameMap = new HashMap(); +- +- FieldDeserializer2Factory fieldFactory = FieldDeserializer2Factory.create(); +- +- addBasic(void.class, "void", BasicSerializer.NULL); +- +- addBasic(Boolean.class, "boolean", BasicSerializer.BOOLEAN); +- addBasic(Byte.class, "byte", BasicSerializer.BYTE); +- addBasic(Short.class, "short", BasicSerializer.SHORT); +- addBasic(Integer.class, "int", BasicSerializer.INTEGER); +- addBasic(Long.class, "long", BasicSerializer.LONG); +- addBasic(Float.class, "float", BasicSerializer.FLOAT); +- addBasic(Double.class, "double", BasicSerializer.DOUBLE); +- addBasic(Character.class, "char", BasicSerializer.CHARACTER_OBJECT); +- addBasic(String.class, "string", BasicSerializer.STRING); +- addBasic(Object.class, "object", BasicSerializer.OBJECT); +- addBasic(java.util.Date.class, "date", BasicSerializer.DATE); +- +- addBasic(boolean.class, "boolean", BasicSerializer.BOOLEAN); +- addBasic(byte.class, "byte", BasicSerializer.BYTE); +- addBasic(short.class, "short", BasicSerializer.SHORT); +- addBasic(int.class, "int", BasicSerializer.INTEGER); +- addBasic(long.class, "long", BasicSerializer.LONG); +- addBasic(float.class, "float", BasicSerializer.FLOAT); +- addBasic(double.class, "double", BasicSerializer.DOUBLE); +- addBasic(char.class, "char", BasicSerializer.CHARACTER); +- +- addBasic(boolean[].class, "[boolean", BasicSerializer.BOOLEAN_ARRAY); +- addBasic(byte[].class, "[byte", BasicSerializer.BYTE_ARRAY); +- _staticSerializerMap.put(byte[].class.getName(), ByteArraySerializer.SER); +- addBasic(short[].class, "[short", BasicSerializer.SHORT_ARRAY); +- addBasic(int[].class, "[int", BasicSerializer.INTEGER_ARRAY); +- addBasic(long[].class, "[long", BasicSerializer.LONG_ARRAY); +- addBasic(float[].class, "[float", BasicSerializer.FLOAT_ARRAY); +- addBasic(double[].class, "[double", BasicSerializer.DOUBLE_ARRAY); +- addBasic(char[].class, "[char", BasicSerializer.CHARACTER_ARRAY); +- addBasic(String[].class, "[string", BasicSerializer.STRING_ARRAY); +- addBasic(Object[].class, "[object", BasicSerializer.OBJECT_ARRAY); +- +- Deserializer objectDeserializer = new JavaDeserializer(Object.class, fieldFactory); +- _staticDeserializerMap.put("object", objectDeserializer); +- _staticClassNameMap.put("object", objectDeserializer); +- +- _staticSerializerMap.put(Class.class.getName(), new ClassSerializer()); +- +- _staticDeserializerMap.put(Number.class.getName(), new BasicDeserializer(BasicSerializer.NUMBER)); +- +- /* +- for (Class cl : new Class[] { BigDecimal.class, File.class, ObjectName.class }) { +- _staticSerializerMap.put(cl, StringValueSerializer.SER); +- _staticDeserializerMap.put(cl, new StringValueDeserializer(cl)); +- } +- +- _staticSerializerMap.put(ObjectName.class, StringValueSerializer.SER); +- try { +- _staticDeserializerMap.put(ObjectName.class, +- new StringValueDeserializer(ObjectName.class)); +- } catch (Throwable e) { +- } +- */ +- +- _staticSerializerMap.put(InetAddress.class.getName(), +- InetAddressSerializer.create()); +- +- _staticSerializerMap.put(java.sql.Date.class.getName(), +- new SqlDateSerializer()); +- _staticSerializerMap.put(java.sql.Time.class.getName(), +- new SqlDateSerializer()); +- _staticSerializerMap.put(java.sql.Timestamp.class.getName(), +- new SqlDateSerializer()); +- +- _staticDeserializerMap.put(java.sql.Date.class.getName(), +- new SqlDateDeserializer(java.sql.Date.class)); +- _staticDeserializerMap.put(java.sql.Time.class.getName(), +- new SqlDateDeserializer(java.sql.Time.class)); +- _staticDeserializerMap.put(java.sql.Timestamp.class.getName(), +- new SqlDateDeserializer(java.sql.Timestamp.class)); +- +- // hessian/3bb5 +- _staticDeserializerMap.put(StackTraceElement.class.getName(), +- new StackTraceElementDeserializer(fieldFactory)); +- +- ClassLoader systemClassLoader = null; +- try { +- systemClassLoader = ClassLoader.getSystemClassLoader(); +- } catch (Exception e) { +- } +- +- _systemClassLoader = systemClassLoader; +- } +-} +- ++/* ++ * Copyright (c) 2001-2008 Caucho Technology, Inc. All rights reserved. ++ * ++ * The Apache Software License, Version 1.1 ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * 3. The end-user documentation included with the redistribution, if ++ * any, must include the following acknowlegement: ++ * "This product includes software developed by the ++ * Caucho Technology (http://www.caucho.com/)." ++ * Alternately, this acknowlegement may appear in the software itself, ++ * if and wherever such third-party acknowlegements normally appear. ++ * ++ * 4. The names "Burlap", "Resin", and "Caucho" must not be used to ++ * endorse or promote products derived from this software without prior ++ * written permission. For written permission, please contact ++ * info@caucho.com. ++ * ++ * 5. Products derived from this software may not be called "Resin" ++ * nor may "Resin" appear in their names without prior written ++ * permission of Caucho Technology. ++ * ++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED ++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++ * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS ++ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, ++ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT ++ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ++ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE ++ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN ++ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * @author Scott Ferguson ++ */ ++ ++package com.caucho.hessian.io; ++ ++import java.io.InputStream; ++import java.lang.ref.SoftReference; ++import java.lang.ref.WeakReference; ++import java.net.InetAddress; ++import java.net.URL; ++import java.util.Enumeration; ++import java.util.HashMap; ++import java.util.HashSet; ++import java.util.Map; ++import java.util.Properties; ++import java.util.WeakHashMap; ++import java.util.concurrent.ConcurrentHashMap; ++import java.util.logging.Level; ++import java.util.logging.Logger; ++ ++import com.caucho.hessian.HessianException; ++ ++/** ++ * The classloader-specific Factory for returning serialization ++ */ ++public class ContextSerializerFactory ++{ ++ private static final Logger log ++ = Logger.getLogger(ContextSerializerFactory.class.getName()); ++ ++ private static Deserializer OBJECT_DESERIALIZER ++ = new BasicDeserializer(BasicDeserializer.OBJECT); ++ ++ private static final WeakHashMap> ++ _contextRefMap ++ = new WeakHashMap>(); ++ ++ private static final ClassLoader _systemClassLoader; ++ ++ private static HashMap _staticSerializerMap; ++ private static HashMap _staticDeserializerMap; ++ private static HashMap _staticClassNameMap; ++ ++ private ContextSerializerFactory _parent; ++ private WeakReference _loaderRef; ++ ++ private final HashSet _serializerFiles = new HashSet(); ++ private final HashSet _deserializerFiles = new HashSet(); ++ ++ private final HashMap _serializerClassMap ++ = new HashMap(); ++ ++ private final ConcurrentHashMap _customSerializerMap ++ = new ConcurrentHashMap(); ++ ++ private final HashMap,Serializer> _serializerInterfaceMap ++ = new HashMap,Serializer>(); ++ ++ private final HashMap _deserializerClassMap ++ = new HashMap(); ++ ++ private final HashMap _deserializerClassNameMap ++ = new HashMap(); ++ ++ private final ConcurrentHashMap _customDeserializerMap ++ = new ConcurrentHashMap(); ++ ++ private final HashMap,Deserializer> _deserializerInterfaceMap ++ = new HashMap,Deserializer>(); ++ ++ public ContextSerializerFactory(ContextSerializerFactory parent, ++ ClassLoader loader) ++ { ++ if (loader == null) ++ loader = _systemClassLoader; ++ ++ _loaderRef = new WeakReference(loader); ++ ++ init(); ++ } ++ ++ public static ContextSerializerFactory create() ++ { ++ return create(Thread.currentThread().getContextClassLoader()); ++ } ++ ++ public static ContextSerializerFactory create(ClassLoader loader) ++ { ++ synchronized (_contextRefMap) { ++ SoftReference factoryRef ++ = _contextRefMap.get(loader); ++ ++ ContextSerializerFactory factory = null; ++ ++ if (factoryRef != null) ++ factory = factoryRef.get(); ++ ++ if (factory == null) { ++ ContextSerializerFactory parent = null; ++ ++ if (loader != null) ++ parent = create(loader.getParent()); ++ ++ factory = new ContextSerializerFactory(parent, loader); ++ factoryRef = new SoftReference(factory); ++ ++ _contextRefMap.put(loader, factoryRef); ++ } ++ ++ return factory; ++ } ++ } ++ ++ public ClassLoader getClassLoader() ++ { ++ WeakReference loaderRef = _loaderRef; ++ ++ if (loaderRef != null) ++ return loaderRef.get(); ++ else ++ return null; ++ } ++ ++ /** ++ * Returns the serializer for a given class. ++ */ ++ public Serializer getSerializer(String className) ++ { ++ Serializer serializer = _serializerClassMap.get(className); ++ ++ if (serializer == AbstractSerializer.NULL) ++ return null; ++ else ++ return serializer; ++ } ++ ++ /** ++ * Returns a custom serializer the class ++ * ++ * @param cl the class of the object that needs to be serialized. ++ * ++ * @return a serializer object for the serialization. ++ */ ++ public Serializer getCustomSerializer(Class cl) ++ { ++ Serializer serializer = _customSerializerMap.get(cl.getName()); ++ ++ if (serializer == AbstractSerializer.NULL) ++ return null; ++ else if (serializer != null) ++ return serializer; ++ ++ try { ++ String className = cl.getName() + "HessianSerializer"; ++ ++ if (cl.getName().equals("java.util.Locale")) { ++ className = "com.caucho.hessian.io.LocaleHessianSerializer"; ++ } ++ ++ Class serClass = Class.forName(className, false, ++ Thread.currentThread().getContextClassLoader()); ++ ++ Serializer ser = (Serializer) serClass.newInstance(); ++ ++ _customSerializerMap.put(cl.getName(), ser); ++ ++ return ser; ++ } catch (ClassNotFoundException e) { ++ log.log(Level.ALL, e.toString(), e); ++ } catch (Exception e) { ++ throw new HessianException(e); ++ } ++ ++ _customSerializerMap.put(cl.getName(), AbstractSerializer.NULL); ++ ++ return null; ++ } ++ ++ /** ++ * Returns the deserializer for a given class. ++ */ ++ public Deserializer getDeserializer(String className) ++ { ++ Deserializer deserializer = _deserializerClassMap.get(className); ++ ++ if (deserializer != null && deserializer != AbstractDeserializer.NULL) { ++ return deserializer; ++ } ++ ++ deserializer = _deserializerInterfaceMap.get(className); ++ ++ if (deserializer != null && deserializer != AbstractDeserializer.NULL) { ++ return deserializer; ++ } ++ ++ return null; ++ } ++ ++ /** ++ * Returns a custom deserializer the class ++ * ++ * @param cl the class of the object that needs to be deserialized. ++ * ++ * @return a deserializer object for the deserialization. ++ */ ++ public Deserializer getCustomDeserializer(Class cl) ++ { ++ Deserializer deserializer = _customDeserializerMap.get(cl.getName()); ++ ++ if (deserializer == AbstractDeserializer.NULL) ++ return null; ++ else if (deserializer != null) ++ return deserializer; ++ ++ try { ++ String className = cl.getName() + "HessianDeserializer"; ++ ++ if (cl.getName().equals("java.util.Locale")) { ++ className = "com.caucho.hessian.io.LocaleHessianDeserializer"; ++ } ++ ++ Class serClass = Class.forName(className, false, ++ Thread.currentThread().getContextClassLoader()); ++ ++ Deserializer ser = (Deserializer) serClass.newInstance(); ++ ++ _customDeserializerMap.put(cl.getName(), ser); ++ ++ return ser; ++ } catch (ClassNotFoundException e) { ++ log.log(Level.ALL, e.toString(), e); ++ } catch (Exception e) { ++ throw new HessianException(e); ++ } ++ ++ _customDeserializerMap.put(cl.getName(), AbstractDeserializer.NULL); ++ ++ return null; ++ } ++ ++ /** ++ * Initialize the factory ++ */ ++ private void init() ++ { ++ if (_parent != null) { ++ _serializerFiles.addAll(_parent._serializerFiles); ++ _deserializerFiles.addAll(_parent._deserializerFiles); ++ ++ _serializerClassMap.putAll(_parent._serializerClassMap); ++ _deserializerClassMap.putAll(_parent._deserializerClassMap); ++ } ++ ++ if (_parent == null) { ++ _serializerClassMap.putAll(_staticSerializerMap); ++ _deserializerClassMap.putAll(_staticDeserializerMap); ++ _deserializerClassNameMap.putAll(_staticClassNameMap); ++ } ++ ++ HashMap classMap; ++ ++ classMap = new HashMap(); ++ initSerializerFiles("META-INF/hessian/serializers", ++ _serializerFiles, ++ classMap, ++ Serializer.class); ++ ++ for (Map.Entry entry : classMap.entrySet()) { ++ try { ++ Serializer ser = (Serializer) entry.getValue().newInstance(); ++ ++ if (entry.getKey().isInterface()) ++ _serializerInterfaceMap.put(entry.getKey(), ser); ++ else ++ _serializerClassMap.put(entry.getKey().getName(), ser); ++ } catch (Exception e) { ++ throw new HessianException(e); ++ } ++ } ++ ++ classMap = new HashMap(); ++ initSerializerFiles("META-INF/hessian/deserializers", ++ _deserializerFiles, ++ classMap, ++ Deserializer.class); ++ ++ for (Map.Entry entry : classMap.entrySet()) { ++ try { ++ Deserializer ser = (Deserializer) entry.getValue().newInstance(); ++ ++ if (entry.getKey().isInterface()) ++ _deserializerInterfaceMap.put(entry.getKey(), ser); ++ else { ++ _deserializerClassMap.put(entry.getKey().getName(), ser); ++ } ++ } catch (Exception e) { ++ throw new HessianException(e); ++ } ++ } ++ } ++ ++ private void initSerializerFiles(String fileName, ++ HashSet fileList, ++ HashMap classMap, ++ Class type) ++ { ++ try { ++ ClassLoader classLoader = getClassLoader(); ++ ++ // on systems with the security manager enabled, the system classloader ++ // is null ++ if (classLoader == null) ++ return; ++ ++ Enumeration iter; ++ ++ iter = classLoader.getResources(fileName); ++ while (iter.hasMoreElements()) { ++ URL url = (URL) iter.nextElement(); ++ ++ if (fileList.contains(url.toString())) ++ continue; ++ ++ fileList.add(url.toString()); ++ ++ InputStream is = null; ++ try { ++ is = url.openStream(); ++ ++ Properties props = new Properties(); ++ props.load(is); ++ ++ for (Map.Entry entry : props.entrySet()) { ++ String apiName = (String) entry.getKey(); ++ String serializerName = (String) entry.getValue(); ++ ++ Class apiClass = null; ++ Class serializerClass = null; ++ ++ try { ++ apiClass = Class.forName(apiName, false, classLoader); ++ } catch (ClassNotFoundException e) { ++ log.fine(url + ": " + apiName + " is not available in this context: " + getClassLoader()); ++ continue; ++ } ++ ++ try { ++ serializerClass = Class.forName(serializerName, false, classLoader); ++ } catch (ClassNotFoundException e) { ++ log.fine(url + ": " + serializerName + " is not available in this context: " + getClassLoader()); ++ continue; ++ } ++ ++ if (! type.isAssignableFrom(serializerClass)) ++ throw new HessianException(url + ": " + serializerClass.getName() + " is invalid because it does not implement " + type.getName()); ++ ++ classMap.put(apiClass, serializerClass); ++ } ++ } finally { ++ if (is != null) ++ is.close(); ++ } ++ } ++ } catch (RuntimeException e) { ++ throw e; ++ } catch (Exception e) { ++ throw new HessianException(e); ++ } ++ } ++ ++ private static void addBasic(Class cl, String typeName, int type) ++ { ++ _staticSerializerMap.put(cl.getName(), new BasicSerializer(type)); ++ ++ Deserializer deserializer = new BasicDeserializer(type); ++ _staticDeserializerMap.put(cl.getName(), deserializer); ++ _staticClassNameMap.put(typeName, deserializer); ++ } ++ ++ static { ++ _staticSerializerMap = new HashMap(); ++ _staticDeserializerMap = new HashMap(); ++ _staticClassNameMap = new HashMap(); ++ ++ FieldDeserializer2Factory fieldFactory = FieldDeserializer2Factory.create(); ++ ++ addBasic(void.class, "void", BasicSerializer.NULL); ++ ++ addBasic(Boolean.class, "boolean", BasicSerializer.BOOLEAN); ++ addBasic(Byte.class, "byte", BasicSerializer.BYTE); ++ addBasic(Short.class, "short", BasicSerializer.SHORT); ++ addBasic(Integer.class, "int", BasicSerializer.INTEGER); ++ addBasic(Long.class, "long", BasicSerializer.LONG); ++ addBasic(Float.class, "float", BasicSerializer.FLOAT); ++ addBasic(Double.class, "double", BasicSerializer.DOUBLE); ++ addBasic(Character.class, "char", BasicSerializer.CHARACTER_OBJECT); ++ addBasic(String.class, "string", BasicSerializer.STRING); ++ addBasic(Object.class, "object", BasicSerializer.OBJECT); ++ addBasic(java.util.Date.class, "date", BasicSerializer.DATE); ++ ++ addBasic(boolean.class, "boolean", BasicSerializer.BOOLEAN); ++ addBasic(byte.class, "byte", BasicSerializer.BYTE); ++ addBasic(short.class, "short", BasicSerializer.SHORT); ++ addBasic(int.class, "int", BasicSerializer.INTEGER); ++ addBasic(long.class, "long", BasicSerializer.LONG); ++ addBasic(float.class, "float", BasicSerializer.FLOAT); ++ addBasic(double.class, "double", BasicSerializer.DOUBLE); ++ addBasic(char.class, "char", BasicSerializer.CHARACTER); ++ ++ addBasic(boolean[].class, "[boolean", BasicSerializer.BOOLEAN_ARRAY); ++ addBasic(byte[].class, "[byte", BasicSerializer.BYTE_ARRAY); ++ _staticSerializerMap.put(byte[].class.getName(), ByteArraySerializer.SER); ++ addBasic(short[].class, "[short", BasicSerializer.SHORT_ARRAY); ++ addBasic(int[].class, "[int", BasicSerializer.INTEGER_ARRAY); ++ addBasic(long[].class, "[long", BasicSerializer.LONG_ARRAY); ++ addBasic(float[].class, "[float", BasicSerializer.FLOAT_ARRAY); ++ addBasic(double[].class, "[double", BasicSerializer.DOUBLE_ARRAY); ++ addBasic(char[].class, "[char", BasicSerializer.CHARACTER_ARRAY); ++ addBasic(String[].class, "[string", BasicSerializer.STRING_ARRAY); ++ addBasic(Object[].class, "[object", BasicSerializer.OBJECT_ARRAY); ++ ++ Deserializer objectDeserializer = new JavaDeserializer(Object.class, fieldFactory); ++ _staticDeserializerMap.put("object", objectDeserializer); ++ _staticClassNameMap.put("object", objectDeserializer); ++ ++ _staticSerializerMap.put(Class.class.getName(), new ClassSerializer()); ++ ++ _staticDeserializerMap.put(Number.class.getName(), new BasicDeserializer(BasicSerializer.NUMBER)); ++ ++ /* ++ for (Class cl : new Class[] { BigDecimal.class, File.class, ObjectName.class }) { ++ _staticSerializerMap.put(cl, StringValueSerializer.SER); ++ _staticDeserializerMap.put(cl, new StringValueDeserializer(cl)); ++ } ++ ++ _staticSerializerMap.put(ObjectName.class, StringValueSerializer.SER); ++ try { ++ _staticDeserializerMap.put(ObjectName.class, ++ new StringValueDeserializer(ObjectName.class)); ++ } catch (Throwable e) { ++ } ++ */ ++ ++ _staticSerializerMap.put(InetAddress.class.getName(), ++ InetAddressSerializer.create()); ++ ++ _staticSerializerMap.put(java.sql.Date.class.getName(), ++ new SqlDateSerializer()); ++ _staticSerializerMap.put(java.sql.Time.class.getName(), ++ new SqlDateSerializer()); ++ _staticSerializerMap.put(java.sql.Timestamp.class.getName(), ++ new SqlDateSerializer()); ++ ++ _staticDeserializerMap.put(java.sql.Date.class.getName(), ++ new SqlDateDeserializer(java.sql.Date.class)); ++ _staticDeserializerMap.put(java.sql.Time.class.getName(), ++ new SqlDateDeserializer(java.sql.Time.class)); ++ _staticDeserializerMap.put(java.sql.Timestamp.class.getName(), ++ new SqlDateDeserializer(java.sql.Timestamp.class)); ++ ++ // hessian/3bb5 ++ _staticDeserializerMap.put(StackTraceElement.class.getName(), ++ new StackTraceElementDeserializer(fieldFactory)); ++ ++ ClassLoader systemClassLoader = null; ++ try { ++ systemClassLoader = ClassLoader.getSystemClassLoader(); ++ } catch (Exception e) { ++ } ++ ++ _systemClassLoader = systemClassLoader; ++ } ++} ++ +diff -Npur hessian-4.0.65-src/com/caucho/hessian/io/LocaleHessianDeserializer.java hessian-4.0.65-fix/com/caucho/hessian/io/LocaleHessianDeserializer.java +--- hessian-4.0.65-src/com/caucho/hessian/io/LocaleHessianDeserializer.java 1970-01-01 08:00:00.000000000 +0800 ++++ hessian-4.0.65-fix/com/caucho/hessian/io/LocaleHessianDeserializer.java 2023-08-15 18:39:22.000000000 +0800 +@@ -0,0 +1,85 @@ ++package com.caucho.hessian.io; ++import com.caucho.hessian.io.AbstractDeserializer; ++import com.caucho.hessian.io.AbstractHessianInput; ++ ++import java.io.IOException; ++import java.util.Locale; ++ ++public class LocaleHessianDeserializer extends AbstractDeserializer { ++ ++ public Class getType() { ++ return Locale.class; ++ } ++ ++ public Object readMap(AbstractHessianInput in) ++ throws IOException { ++ int ref = in.addRef(null); ++ ++ String languageValue = null; ++ String countryValue = null; ++ String variantValue = null; ++ ++ while (!in.isEnd()) { ++ String key = in.readString(); ++ ++ if (key.equals("language")) ++ languageValue = in.readString(); ++ else if (key.equals("country")) ++ countryValue = in.readString(); ++ else if (key.equals("variant")) ++ variantValue = in.readString(); ++ else ++ in.readString(); ++ } ++ ++ in.readMapEnd(); ++ ++ Object value = getObject(languageValue, countryValue, variantValue); ++ ++ in.setRef(ref, value); ++ ++ return value; ++ } ++ ++ @Override ++ public Object readObject(AbstractHessianInput in, Object[] fields) throws IOException { ++ int ref = in.addRef(null); ++ ++ String languageValue = null; ++ String countryValue = null; ++ String variantValue = null; ++ ++ for (Object key : fields) { ++ if (key.equals("language")) ++ languageValue = in.readString(); ++ else if (key.equals("country")) ++ countryValue = in.readString(); ++ else if (key.equals("variant")) ++ variantValue = in.readString(); ++ else ++ in.readObject(); ++ ++ } ++ ++ Object value = getObject(languageValue, countryValue, variantValue); ++ ++ in.setRef(ref, value); ++ ++ return value; ++ } ++ ++ private Object getObject(String languageValue, String countryValue, String variantValue) { ++ Object value = null; ++ if (languageValue != null && countryValue != null && variantValue != null) { ++ value = new Locale(languageValue, countryValue, variantValue); ++ } else if (languageValue != null && countryValue != null) { ++ value = new Locale(languageValue, countryValue); ++ } else if (languageValue != null) { ++ value = new Locale(languageValue); ++ } else { ++ value = Locale.getDefault(); ++ } ++ return value; ++ } ++ ++} +\ No newline at end of file +diff -Npur hessian-4.0.65-src/com/caucho/hessian/io/LocaleHessianSerializer.java hessian-4.0.65-fix/com/caucho/hessian/io/LocaleHessianSerializer.java +--- hessian-4.0.65-src/com/caucho/hessian/io/LocaleHessianSerializer.java 1970-01-01 08:00:00.000000000 +0800 ++++ hessian-4.0.65-fix/com/caucho/hessian/io/LocaleHessianSerializer.java 2023-08-15 18:39:22.000000000 +0800 +@@ -0,0 +1,64 @@ ++package com.caucho.hessian.io; ++import com.caucho.hessian.io.AbstractHessianOutput; ++import com.caucho.hessian.io.AbstractSerializer; ++ ++import java.io.IOException; ++import java.util.Locale; ++ ++public class LocaleHessianSerializer extends AbstractSerializer ++{ ++ public void writeObject(Object obj, AbstractHessianOutput out) ++ throws IOException ++ { ++ ++ if (obj == null) ++ out.writeNull(); ++ else ++ { ++ Class cl = obj.getClass(); ++ ++ if (out.addRef(obj)) ++ return; ++ ++ int ref = out.writeObjectBegin(cl.getName()); ++ ++ Locale loc = (Locale) obj; ++ ++ if (ref < -1) ++ { ++ if (loc.getLanguage() != null) ++ { ++ out.writeString("language"); ++ out.writeString(loc.getLanguage()); ++ } ++ if (loc.getCountry() != null) ++ { ++ out.writeString("country"); ++ out.writeString(loc.getCountry()); ++ } ++ if (loc.getVariant() != null) ++ { ++ out.writeString("variant"); ++ out.writeString(loc.getVariant()); ++ } ++ ++ out.writeMapEnd(); ++ } ++ else ++ { ++ if (ref == -1) ++ { ++ out.writeInt(3); ++ out.writeString("language"); ++ out.writeString("country"); ++ out.writeString("variant"); ++ out.writeObjectBegin(cl.getName()); ++ } ++ ++ out.writeString(loc.getLanguage()); ++ out.writeString(loc.getCountry()); ++ out.writeString(loc.getVariant()); ++ } ++ } ++ } ++} +\ No newline at end of file +diff -Npur hessian-4.0.65-src/com/caucho/hessian/io/NonTransientUnsafeDeserializer.java hessian-4.0.65-fix/com/caucho/hessian/io/NonTransientUnsafeDeserializer.java +--- hessian-4.0.65-src/com/caucho/hessian/io/NonTransientUnsafeDeserializer.java 1970-01-01 08:00:00.000000000 +0800 ++++ hessian-4.0.65-fix/com/caucho/hessian/io/NonTransientUnsafeDeserializer.java 2023-08-15 18:39:22.000000000 +0800 +@@ -0,0 +1,755 @@ ++/** ++ * ++ */ ++package com.caucho.hessian.io; ++ ++import java.io.IOException; ++import java.lang.reflect.Field; ++import java.lang.reflect.InvocationTargetException; ++import java.lang.reflect.Method; ++import java.lang.reflect.Modifier; ++import java.util.HashMap; ++import java.util.logging.Level; ++import java.util.logging.Logger; ++ ++import sun.misc.Unsafe; ++ ++/** ++ * @author l65882 ++ * ++ */ ++public class NonTransientUnsafeDeserializer extends AbstractMapDeserializer { ++ private static final Logger log ++ = Logger.getLogger(JavaDeserializer.class.getName()); ++ ++ private static boolean _isEnabled; ++ @SuppressWarnings("restriction") ++ private static Unsafe _unsafe; ++ ++ private Class _type; ++ private HashMap _fieldMap; ++ private Method _readResolve; ++ ++ public NonTransientUnsafeDeserializer(Class cl) ++ { ++ _type = cl; ++ _fieldMap = getFieldMap(cl); ++ ++ _readResolve = getReadResolve(cl); ++ ++ if (_readResolve != null) { ++ _readResolve.setAccessible(true); ++ } ++ } ++ ++ public static boolean isEnabled() ++ { ++ return _isEnabled; ++ } ++ ++ @Override ++ public Class getType() ++ { ++ return _type; ++ } ++ ++ @Override ++ public boolean isReadResolve() ++ { ++ return _readResolve != null; ++ } ++ ++ public Object readMap(AbstractHessianInput in) ++ throws IOException ++ { ++ try { ++ Object obj = instantiate(); ++ ++ return readMap(in, obj); ++ } catch (IOException e) { ++ throw e; ++ } catch (RuntimeException e) { ++ throw e; ++ } catch (Exception e) { ++ throw new IOExceptionWrapper(_type.getName() + ":" + e.getMessage(), e); ++ } ++ } ++ ++ @Override ++ public Object []createFields(int len) ++ { ++ return new FieldDeserializer[len]; ++ } ++ ++ public Object createField(String name) ++ { ++ Object reader = _fieldMap.get(name); ++ ++ if (reader == null) ++ reader = NullFieldDeserializer.DESER; ++ ++ return reader; ++ } ++ ++ @Override ++ public Object readObject(AbstractHessianInput in, ++ Object []fields) ++ throws IOException ++ { ++ try { ++ Object obj = instantiate(); ++ ++ return readObject(in, obj, (FieldDeserializer []) fields); ++ } catch (IOException e) { ++ throw e; ++ } catch (RuntimeException e) { ++ throw e; ++ } catch (Exception e) { ++ throw new IOExceptionWrapper(_type.getName() + ":" + e.getMessage(), e); ++ } ++ } ++ ++ @Override ++ public Object readObject(AbstractHessianInput in, ++ String []fieldNames) ++ throws IOException ++ { ++ try { ++ Object obj = instantiate(); ++ ++ return readObject(in, obj, fieldNames); ++ } catch (IOException e) { ++ throw e; ++ } catch (RuntimeException e) { ++ throw e; ++ } catch (Exception e) { ++ throw new IOExceptionWrapper(_type.getName() + ":" + e.getMessage(), e); ++ } ++ } ++ ++ /** ++ * Returns the readResolve method ++ */ ++ protected Method getReadResolve(Class cl) ++ { ++ for (; cl != null; cl = cl.getSuperclass()) { ++ Method []methods = cl.getDeclaredMethods(); ++ ++ for (int i = 0; i < methods.length; i++) { ++ Method method = methods[i]; ++ ++ if (method.getName().equals("readResolve") ++ && method.getParameterTypes().length == 0) ++ return method; ++ } ++ } ++ ++ return null; ++ } ++ ++ public Object readMap(AbstractHessianInput in, Object obj) ++ throws IOException ++ { ++ try { ++ int ref = in.addRef(obj); ++ ++ while (! in.isEnd()) { ++ Object key = in.readObject(); ++ ++ FieldDeserializer deser = (FieldDeserializer) _fieldMap.get(key); ++ ++ if (deser != null) ++ deser.deserialize(in, obj); ++ else ++ in.readObject(); ++ } ++ ++ in.readMapEnd(); ++ ++ Object resolve = resolve(in, obj); ++ ++ if (obj != resolve) ++ in.setRef(ref, resolve); ++ ++ return resolve; ++ } catch (IOException e) { ++ throw e; ++ } catch (Exception e) { ++ throw new IOExceptionWrapper(e); ++ } ++ } ++ ++ public Object readObject(AbstractHessianInput in, ++ Object obj, ++ FieldDeserializer []fields) ++ throws IOException ++ { ++ try { ++ int ref = in.addRef(obj); ++ ++ for (FieldDeserializer reader : fields) { ++ reader.deserialize(in, obj); ++ } ++ ++ Object resolve = resolve(in, obj); ++ ++ if (obj != resolve) ++ in.setRef(ref, resolve); ++ ++ return resolve; ++ } catch (IOException e) { ++ throw e; ++ } catch (Exception e) { ++ throw new IOExceptionWrapper(obj.getClass().getName() + ":" + e, e); ++ } ++ } ++ ++ public Object readObject(AbstractHessianInput in, ++ Object obj, ++ String []fieldNames) ++ throws IOException ++ { ++ try { ++ int ref = in.addRef(obj); ++ ++ for (String fieldName : fieldNames) { ++ FieldDeserializer reader = _fieldMap.get(fieldName); ++ ++ if (reader != null) ++ reader.deserialize(in, obj); ++ else ++ in.readObject(); ++ } ++ ++ Object resolve = resolve(in, obj); ++ ++ if (obj != resolve) ++ in.setRef(ref, resolve); ++ ++ return resolve; ++ } catch (IOException e) { ++ throw e; ++ } catch (Exception e) { ++ throw new IOExceptionWrapper(obj.getClass().getName() + ":" + e, e); ++ } ++ } ++ ++ protected Object resolve(AbstractHessianInput in, Object obj) ++ throws Exception ++ { ++ // if there's a readResolve method, call it ++ try { ++ if (_readResolve != null) ++ return _readResolve.invoke(obj, new Object[0]); ++ } catch (InvocationTargetException e) { ++ if (e.getCause() instanceof Exception) ++ throw (Exception) e.getCause(); ++ else ++ throw e; ++ } ++ ++ return obj; ++ } ++ ++ @SuppressWarnings("restriction") ++ protected Object instantiate() ++ throws Exception ++ { ++ return _unsafe.allocateInstance(_type); ++ } ++ ++ /** ++ * Creates a map of the classes fields. ++ */ ++ protected HashMap getFieldMap(Class cl) ++ { ++ HashMap fieldMap ++ = new HashMap(); ++ ++ for (; cl != null; cl = cl.getSuperclass()) { ++ Field []fields = cl.getDeclaredFields(); ++ for (int i = 0; i < fields.length; i++) { ++ Field field = fields[i]; ++ ++ if (Modifier.isStatic(field.getModifiers())) ++ continue; ++ else if (fieldMap.get(field.getName()) != null) ++ continue; ++ // XXX: could parameterize the handler to only deal with public ++ try { ++ field.setAccessible(true); ++ } catch (Throwable e) { ++ e.printStackTrace(); ++ } ++ ++ Class type = field.getType(); ++ FieldDeserializer deser; ++ ++ if (String.class.equals(type)) { ++ deser = new StringFieldDeserializer(field); ++ } ++ else if (byte.class.equals(type)) { ++ deser = new ByteFieldDeserializer(field); ++ } ++ else if (char.class.equals(type)) { ++ deser = new CharFieldDeserializer(field); ++ } ++ else if (short.class.equals(type)) { ++ deser = new ShortFieldDeserializer(field); ++ } ++ else if (int.class.equals(type)) { ++ deser = new IntFieldDeserializer(field); ++ } ++ else if (long.class.equals(type)) { ++ deser = new LongFieldDeserializer(field); ++ } ++ else if (float.class.equals(type)) { ++ deser = new FloatFieldDeserializer(field); ++ } ++ else if (double.class.equals(type)) { ++ deser = new DoubleFieldDeserializer(field); ++ } ++ else if (boolean.class.equals(type)) { ++ deser = new BooleanFieldDeserializer(field); ++ } ++ else if (java.sql.Date.class.equals(type)) { ++ deser = new SqlDateFieldDeserializer(field); ++ } ++ else if (java.sql.Timestamp.class.equals(type)) { ++ deser = new SqlTimestampFieldDeserializer(field); ++ } ++ else if (java.sql.Time.class.equals(type)) { ++ deser = new SqlTimeFieldDeserializer(field); ++ } ++ else { ++ deser = new ObjectFieldDeserializer(field); ++ } ++ ++ fieldMap.put(field.getName(), deser); ++ } ++ } ++ ++ return fieldMap; ++ } ++ ++ abstract static class FieldDeserializer { ++ abstract void deserialize(AbstractHessianInput in, Object obj) ++ throws IOException; ++ } ++ ++ static class NullFieldDeserializer extends FieldDeserializer { ++ static NullFieldDeserializer DESER = new NullFieldDeserializer(); ++ void deserialize(AbstractHessianInput in, Object obj) ++ throws IOException ++ { ++ in.readObject(); ++ } ++ } ++ ++ static class ObjectFieldDeserializer extends FieldDeserializer { ++ private final Field _field; ++ private final long _offset; ++ ++ @SuppressWarnings("restriction") ++ ObjectFieldDeserializer(Field field) ++ { ++ _field = field; ++ _offset = _unsafe.objectFieldOffset(_field); ++ } ++ ++ @SuppressWarnings("restriction") ++ void deserialize(AbstractHessianInput in, Object obj) ++ throws IOException ++ { ++ Object value = null; ++ ++ try { ++ value = in.readObject(_field.getType()); ++ ++ _unsafe.putObject(obj, _offset, value); ++ } catch (Exception e) { ++ logDeserializeError(_field, obj, value, e); ++ } ++ } ++ } ++ ++ static class BooleanFieldDeserializer extends FieldDeserializer { ++ private final Field _field; ++ private final long _offset; ++ ++ @SuppressWarnings("restriction") ++ BooleanFieldDeserializer(Field field) ++ { ++ _field = field; ++ _offset = _unsafe.objectFieldOffset(_field); ++ } ++ ++ @SuppressWarnings("restriction") ++ void deserialize(AbstractHessianInput in, Object obj) ++ throws IOException ++ { ++ boolean value = false; ++ ++ try { ++ value = in.readBoolean(); ++ ++ _unsafe.putBoolean(obj, _offset, value); ++ } catch (Exception e) { ++ logDeserializeError(_field, obj, value, e); ++ } ++ } ++ } ++ ++ static class ByteFieldDeserializer extends FieldDeserializer { ++ private final Field _field; ++ private final long _offset; ++ ++ @SuppressWarnings("restriction") ++ ByteFieldDeserializer(Field field) ++ { ++ _field = field; ++ _offset = _unsafe.objectFieldOffset(_field); ++ } ++ ++ @SuppressWarnings("restriction") ++ void deserialize(AbstractHessianInput in, Object obj) ++ throws IOException ++ { ++ int value = 0; ++ ++ try { ++ value = in.readInt(); ++ ++ _unsafe.putByte(obj, _offset, (byte) value); ++ } catch (Exception e) { ++ logDeserializeError(_field, obj, value, e); ++ } ++ } ++ } ++ ++ static class CharFieldDeserializer extends FieldDeserializer { ++ private final Field _field; ++ private final long _offset; ++ ++ @SuppressWarnings("restriction") ++ CharFieldDeserializer(Field field) ++ { ++ _field = field; ++ _offset = _unsafe.objectFieldOffset(_field); ++ } ++ ++ @SuppressWarnings("restriction") ++ void deserialize(AbstractHessianInput in, Object obj) ++ throws IOException ++ { ++ String value = null; ++ ++ try { ++ value = in.readString(); ++ ++ char ch; ++ ++ if (value != null && value.length() > 0) ++ ch = value.charAt(0); ++ else ++ ch = 0; ++ ++ _unsafe.putChar(obj, _offset, ch); ++ } catch (Exception e) { ++ logDeserializeError(_field, obj, value, e); ++ } ++ } ++ } ++ ++ static class ShortFieldDeserializer extends FieldDeserializer { ++ private final Field _field; ++ private final long _offset; ++ ++ @SuppressWarnings("restriction") ++ ShortFieldDeserializer(Field field) ++ { ++ _field = field; ++ _offset = _unsafe.objectFieldOffset(_field); ++ } ++ ++ @SuppressWarnings("restriction") ++ void deserialize(AbstractHessianInput in, Object obj) ++ throws IOException ++ { ++ int value = 0; ++ ++ try { ++ value = in.readInt(); ++ ++ _unsafe.putShort(obj, _offset, (short) value); ++ } catch (Exception e) { ++ logDeserializeError(_field, obj, value, e); ++ } ++ } ++ } ++ ++ static class IntFieldDeserializer extends FieldDeserializer { ++ private final Field _field; ++ private final long _offset; ++ ++ @SuppressWarnings("restriction") ++ IntFieldDeserializer(Field field) ++ { ++ _field = field; ++ _offset = _unsafe.objectFieldOffset(_field); ++ } ++ ++ @SuppressWarnings("restriction") ++ void deserialize(AbstractHessianInput in, Object obj) ++ throws IOException ++ { ++ int value = 0; ++ ++ try { ++ value = in.readInt(); ++ ++ _unsafe.putInt(obj, _offset, value); ++ } catch (Exception e) { ++ logDeserializeError(_field, obj, value, e); ++ } ++ } ++ } ++ ++ static class LongFieldDeserializer extends FieldDeserializer { ++ private final Field _field; ++ private final long _offset; ++ ++ @SuppressWarnings("restriction") ++ LongFieldDeserializer(Field field) ++ { ++ _field = field; ++ _offset = _unsafe.objectFieldOffset(_field); ++ } ++ ++ @SuppressWarnings("restriction") ++ void deserialize(AbstractHessianInput in, Object obj) ++ throws IOException ++ { ++ long value = 0; ++ ++ try { ++ value = in.readLong(); ++ ++ _unsafe.putLong(obj, _offset, value); ++ } catch (Exception e) { ++ logDeserializeError(_field, obj, value, e); ++ } ++ } ++ } ++ ++ static class FloatFieldDeserializer extends FieldDeserializer { ++ private final Field _field; ++ private final long _offset; ++ ++ @SuppressWarnings("restriction") ++ FloatFieldDeserializer(Field field) ++ { ++ _field = field; ++ _offset = _unsafe.objectFieldOffset(_field); ++ } ++ ++ void deserialize(AbstractHessianInput in, Object obj) ++ throws IOException ++ { ++ double value = 0; ++ ++ try { ++ value = in.readDouble(); ++ ++ _unsafe.putFloat(obj, _offset, (float) value); ++ } catch (Exception e) { ++ logDeserializeError(_field, obj, value, e); ++ } ++ } ++ } ++ ++ static class DoubleFieldDeserializer extends FieldDeserializer { ++ private final Field _field; ++ private final long _offset; ++ ++ DoubleFieldDeserializer(Field field) ++ { ++ _field = field; ++ _offset = _unsafe.objectFieldOffset(_field); ++ } ++ ++ @SuppressWarnings("restriction") ++ void deserialize(AbstractHessianInput in, Object obj) ++ throws IOException ++ { ++ double value = 0; ++ ++ try { ++ value = in.readDouble(); ++ ++ _unsafe.putDouble(obj, _offset, value); ++ } catch (Exception e) { ++ logDeserializeError(_field, obj, value, e); ++ } ++ } ++ } ++ ++ static class StringFieldDeserializer extends FieldDeserializer { ++ private final Field _field; ++ private final long _offset; ++ ++ @SuppressWarnings("restriction") ++ StringFieldDeserializer(Field field) ++ { ++ _field = field; ++ _offset = _unsafe.objectFieldOffset(_field); ++ } ++ ++ @SuppressWarnings("restriction") ++ void deserialize(AbstractHessianInput in, Object obj) ++ throws IOException ++ { ++ String value = null; ++ ++ try { ++ value = in.readString(); ++ ++ _unsafe.putObject(obj, _offset, value); ++ } catch (Exception e) { ++ logDeserializeError(_field, obj, value, e); ++ } ++ } ++ } ++ ++ static class SqlDateFieldDeserializer extends FieldDeserializer { ++ private final Field _field; ++ private final long _offset; ++ ++ @SuppressWarnings("restriction") ++ SqlDateFieldDeserializer(Field field) ++ { ++ _field = field; ++ _offset = _unsafe.objectFieldOffset(_field); ++ } ++ ++ @SuppressWarnings("restriction") ++ void deserialize(AbstractHessianInput in, Object obj) ++ throws IOException ++ { ++ java.sql.Date value = null; ++ ++ try { ++ java.util.Date date = (java.util.Date) in.readObject(); ++ value = new java.sql.Date(date.getTime()); ++ ++ _unsafe.putObject(obj, _offset, value); ++ } catch (Exception e) { ++ logDeserializeError(_field, obj, value, e); ++ } ++ } ++ } ++ ++ static class SqlTimestampFieldDeserializer extends FieldDeserializer { ++ private final Field _field; ++ private final long _offset; ++ ++ @SuppressWarnings("restriction") ++ SqlTimestampFieldDeserializer(Field field) ++ { ++ _field = field; ++ _offset = _unsafe.objectFieldOffset(_field); ++ } ++ ++ @SuppressWarnings("restriction") ++ void deserialize(AbstractHessianInput in, Object obj) ++ throws IOException ++ { ++ java.sql.Timestamp value = null; ++ ++ try { ++ java.util.Date date = (java.util.Date) in.readObject(); ++ value = new java.sql.Timestamp(date.getTime()); ++ ++ _unsafe.putObject(obj, _offset, value); ++ } catch (Exception e) { ++ logDeserializeError(_field, obj, value, e); ++ } ++ } ++ } ++ ++ static class SqlTimeFieldDeserializer extends FieldDeserializer { ++ private final Field _field; ++ private final long _offset; ++ ++ @SuppressWarnings("restriction") ++ SqlTimeFieldDeserializer(Field field) ++ { ++ _field = field; ++ _offset = _unsafe.objectFieldOffset(_field); ++ } ++ ++ @SuppressWarnings("restriction") ++ void deserialize(AbstractHessianInput in, Object obj) ++ throws IOException ++ { ++ java.sql.Time value = null; ++ ++ try { ++ java.util.Date date = (java.util.Date) in.readObject(); ++ value = new java.sql.Time(date.getTime()); ++ ++ _unsafe.putObject(obj, _offset, value); ++ } catch (Exception e) { ++ logDeserializeError(_field, obj, value, e); ++ } ++ } ++ } ++ ++ static void logDeserializeError(Field field, Object obj, Object value, ++ Throwable e) ++ throws IOException ++ { ++ String fieldName = (field.getDeclaringClass().getName() ++ + "." + field.getName()); ++ ++ if (e instanceof HessianFieldException) ++ throw (HessianFieldException) e; ++ else if (e instanceof IOException) ++ throw new HessianFieldException(fieldName + ": " + e.getMessage(), e); ++ ++ if (value != null) ++ throw new HessianFieldException(fieldName + ": " + value.getClass().getName() + " (" + value + ")" ++ + " cannot be assigned to '" + field.getType().getName() + "'", e); ++ else ++ throw new HessianFieldException(fieldName + ": " + field.getType().getName() + " cannot be assigned from null", e); ++ } ++ ++ static { ++ boolean isEnabled = false; ++ ++ try { ++ Class unsafe = Class.forName("sun.misc.Unsafe"); ++ Field theUnsafe = null; ++ for (Field field : unsafe.getDeclaredFields()) { ++ if (field.getName().equals("theUnsafe")) ++ theUnsafe = field; ++ } ++ ++ if (theUnsafe != null) { ++ theUnsafe.setAccessible(true); ++ _unsafe = (Unsafe) theUnsafe.get(null); ++ } ++ ++ isEnabled = _unsafe != null; ++ ++ String unsafeProp = System.getProperty("com.caucho.hessian.unsafe"); ++ ++ if ("false".equals(unsafeProp)) ++ isEnabled = false; ++ } catch (Throwable e) { ++ log.log(Level.FINER, e.toString(), e); ++ } ++ ++ _isEnabled = isEnabled; ++ } ++} +diff -Npur hessian-4.0.65-src/com/caucho/hessian/io/NonTransientUnsafeSerializer.java hessian-4.0.65-fix/com/caucho/hessian/io/NonTransientUnsafeSerializer.java +--- hessian-4.0.65-src/com/caucho/hessian/io/NonTransientUnsafeSerializer.java 1970-01-01 08:00:00.000000000 +0800 ++++ hessian-4.0.65-fix/com/caucho/hessian/io/NonTransientUnsafeSerializer.java 2023-08-15 18:39:22.000000000 +0800 +@@ -0,0 +1,518 @@ ++/** ++ * ++ */ ++package com.caucho.hessian.io; ++ ++import java.io.IOException; ++import java.lang.ref.SoftReference; ++import java.lang.reflect.Field; ++import java.lang.reflect.Modifier; ++import java.util.ArrayList; ++import java.util.WeakHashMap; ++import java.util.logging.Level; ++import java.util.logging.Logger; ++ ++import sun.misc.Unsafe; ++ ++ ++ ++/** ++ * @author l65882 ++ * ++ */ ++public class NonTransientUnsafeSerializer extends AbstractSerializer { ++ ++ private static final Logger log ++ = Logger.getLogger(NonTransientUnsafeSerializer.class.getName()); ++ ++ private static boolean _isEnabled; ++ private static Unsafe _unsafe; ++ ++ private static final WeakHashMap,SoftReference> _serializerMap ++ = new WeakHashMap,SoftReference>(); ++ ++ private static Object []NULL_ARGS = new Object[0]; ++ ++ private Field []_fields; ++ private FieldSerializer []_fieldSerializers; ++ ++ public static boolean isEnabled() ++ { ++ return _isEnabled; ++ } ++ ++ public NonTransientUnsafeSerializer(Class cl) ++ { ++ introspect(cl); ++ } ++ ++ public static NonTransientUnsafeSerializer create(Class cl) ++ { ++ ClassLoader loader = cl.getClassLoader(); ++ ++ synchronized (_serializerMap) { ++ SoftReference baseRef ++ = _serializerMap.get(cl); ++ ++ NonTransientUnsafeSerializer base = baseRef != null ? baseRef.get() : null; ++ ++ if (base == null) { ++ base = new NonTransientUnsafeSerializer(cl); ++ baseRef = new SoftReference(base); ++ _serializerMap.put(cl, baseRef); ++ } ++ ++ return base; ++ } ++ } ++ ++ protected void introspect(Class cl) ++ { ++ ArrayList primitiveFields = new ArrayList(); ++ ArrayList compoundFields = new ArrayList(); ++ ++ for (; cl != null; cl = cl.getSuperclass()) { ++ Field []fields = cl.getDeclaredFields(); ++ for (int i = 0; i < fields.length; i++) { ++ Field field = fields[i]; ++ ++ if (Modifier.isStatic(field.getModifiers())) ++ continue; ++ ++ // XXX: could parameterize the handler to only deal with public ++ field.setAccessible(true); ++ ++ if (field.getType().isPrimitive() ++ || (field.getType().getName().startsWith("java.lang.") ++ && ! field.getType().equals(Object.class))) ++ primitiveFields.add(field); ++ else ++ compoundFields.add(field); ++ } ++ } ++ ++ ArrayList fields = new ArrayList(); ++ fields.addAll(primitiveFields); ++ fields.addAll(compoundFields); ++ ++ _fields = new Field[fields.size()]; ++ fields.toArray(_fields); ++ ++ _fieldSerializers = new FieldSerializer[_fields.length]; ++ ++ for (int i = 0; i < _fields.length; i++) { ++ _fieldSerializers[i] = getFieldSerializer(_fields[i]); ++ } ++ } ++ ++ @Override ++ public void writeObject(Object obj, AbstractHessianOutput out) ++ throws IOException ++ { ++ if (out.addRef(obj)) { ++ return; ++ } ++ ++ Class cl = obj.getClass(); ++ ++ int ref = out.writeObjectBegin(cl.getName()); ++ ++ if (ref >= 0) { ++ writeInstance(obj, out); ++ } ++ else if (ref == -1) { ++ writeDefinition20(out); ++ out.writeObjectBegin(cl.getName()); ++ writeInstance(obj, out); ++ } ++ else { ++ writeObject10(obj, out); ++ } ++ } ++ ++ protected void writeObject10(Object obj, AbstractHessianOutput out) ++ throws IOException ++ { ++ for (int i = 0; i < _fields.length; i++) { ++ Field field = _fields[i]; ++ ++ out.writeString(field.getName()); ++ ++ _fieldSerializers[i].serialize(out, obj); ++ } ++ ++ out.writeMapEnd(); ++ } ++ ++ private void writeDefinition20(AbstractHessianOutput out) ++ throws IOException ++ { ++ out.writeClassFieldLength(_fields.length); ++ ++ for (int i = 0; i < _fields.length; i++) { ++ Field field = _fields[i]; ++ ++ out.writeString(field.getName()); ++ } ++ } ++ ++ final public void writeInstance(Object obj, AbstractHessianOutput out) ++ throws IOException ++ { ++ try { ++ FieldSerializer []fieldSerializers = _fieldSerializers; ++ int length = fieldSerializers.length; ++ ++ for (int i = 0; i < length; i++) { ++ fieldSerializers[i].serialize(out, obj); ++ } ++ } catch (RuntimeException e) { ++ throw new RuntimeException(e.getMessage() + "\n class: " ++ + obj.getClass().getName() ++ + " (object=" + obj + ")", ++ e); ++ } catch (IOException e) { ++ throw new IOExceptionWrapper(e.getMessage() + "\n class: " ++ + obj.getClass().getName() ++ + " (object=" + obj + ")", ++ e); ++ } ++ } ++ ++ private static FieldSerializer getFieldSerializer(Field field) ++ { ++ Class type = field.getType(); ++ ++ if (boolean.class.equals(type)) { ++ return new BooleanFieldSerializer(field); ++ } ++ else if (byte.class.equals(type)) { ++ return new ByteFieldSerializer(field); ++ } ++ else if (char.class.equals(type)) { ++ return new CharFieldSerializer(field); ++ } ++ else if (short.class.equals(type)) { ++ return new ShortFieldSerializer(field); ++ } ++ else if (int.class.equals(type)) { ++ return new IntFieldSerializer(field); ++ } ++ else if (long.class.equals(type)) { ++ return new LongFieldSerializer(field); ++ } ++ else if (double.class.equals(type)) { ++ return new DoubleFieldSerializer(field); ++ } ++ else if (float.class.equals(type)) { ++ return new FloatFieldSerializer(field); ++ } ++ else if (String.class.equals(type)) { ++ return new StringFieldSerializer(field); ++ } ++ else if (java.util.Date.class.equals(type) ++ || java.sql.Date.class.equals(type) ++ || java.sql.Timestamp.class.equals(type) ++ || java.sql.Time.class.equals(type)) { ++ return new DateFieldSerializer(field); ++ } ++ else ++ return new ObjectFieldSerializer(field); ++ } ++ ++ abstract static class FieldSerializer { ++ abstract void serialize(AbstractHessianOutput out, Object obj) ++ throws IOException; ++ } ++ ++ final static class ObjectFieldSerializer extends FieldSerializer { ++ private final Field _field; ++ private final long _offset; ++ ++ ObjectFieldSerializer(Field field) ++ { ++ _field = field; ++ _offset = _unsafe.objectFieldOffset(field); ++ ++ if (_offset == Unsafe.INVALID_FIELD_OFFSET) ++ throw new IllegalStateException(); ++ } ++ ++ @Override ++ final void serialize(AbstractHessianOutput out, Object obj) ++ throws IOException ++ { ++ try { ++ Object value = _unsafe.getObject(obj, _offset); ++ ++ out.writeObject(value); ++ } catch (RuntimeException e) { ++ throw new RuntimeException(e.getMessage() + "\n field: " ++ + _field.getDeclaringClass().getName() ++ + '.' + _field.getName(), ++ e); ++ } catch (IOException e) { ++ throw new IOExceptionWrapper(e.getMessage() + "\n field: " ++ + _field.getDeclaringClass().getName() ++ + '.' + _field.getName(), ++ e); ++ } ++ } ++ } ++ ++ final static class BooleanFieldSerializer extends FieldSerializer { ++ private final Field _field; ++ private final long _offset; ++ ++ BooleanFieldSerializer(Field field) ++ { ++ _field = field; ++ _offset = _unsafe.objectFieldOffset(field); ++ ++ if (_offset == Unsafe.INVALID_FIELD_OFFSET) ++ throw new IllegalStateException(); ++ } ++ ++ void serialize(AbstractHessianOutput out, Object obj) ++ throws IOException ++ { ++ boolean value = _unsafe.getBoolean(obj, _offset); ++ ++ out.writeBoolean(value); ++ } ++ } ++ ++ final static class ByteFieldSerializer extends FieldSerializer { ++ private final Field _field; ++ private final long _offset; ++ ++ ByteFieldSerializer(Field field) ++ { ++ _field = field; ++ _offset = _unsafe.objectFieldOffset(field); ++ ++ if (_offset == Unsafe.INVALID_FIELD_OFFSET) ++ throw new IllegalStateException(); ++ } ++ ++ final void serialize(AbstractHessianOutput out, Object obj) ++ throws IOException ++ { ++ int value = _unsafe.getByte(obj, _offset); ++ ++ out.writeInt(value); ++ } ++ } ++ ++ final static class CharFieldSerializer extends FieldSerializer { ++ private final Field _field; ++ private final long _offset; ++ ++ CharFieldSerializer(Field field) ++ { ++ _field = field; ++ _offset = _unsafe.objectFieldOffset(field); ++ ++ if (_offset == Unsafe.INVALID_FIELD_OFFSET) ++ throw new IllegalStateException(); ++ } ++ ++ final void serialize(AbstractHessianOutput out, Object obj) ++ throws IOException ++ { ++ char value = _unsafe.getChar(obj, _offset); ++ ++ out.writeString(String.valueOf(value)); ++ } ++ } ++ ++ final static class ShortFieldSerializer extends FieldSerializer { ++ private final Field _field; ++ private final long _offset; ++ ++ ShortFieldSerializer(Field field) ++ { ++ _field = field; ++ _offset = _unsafe.objectFieldOffset(field); ++ ++ if (_offset == Unsafe.INVALID_FIELD_OFFSET) ++ throw new IllegalStateException(); ++ } ++ ++ final void serialize(AbstractHessianOutput out, Object obj) ++ throws IOException ++ { ++ int value = _unsafe.getShort(obj, _offset); ++ ++ out.writeInt(value); ++ } ++ } ++ ++ final static class IntFieldSerializer extends FieldSerializer { ++ private final Field _field; ++ private final long _offset; ++ ++ IntFieldSerializer(Field field) ++ { ++ _field = field; ++ _offset = _unsafe.objectFieldOffset(field); ++ ++ if (_offset == Unsafe.INVALID_FIELD_OFFSET) ++ throw new IllegalStateException(); ++ } ++ ++ final void serialize(AbstractHessianOutput out, Object obj) ++ throws IOException ++ { ++ int value = _unsafe.getInt(obj, _offset); ++ ++ out.writeInt(value); ++ } ++ } ++ ++ final static class LongFieldSerializer extends FieldSerializer { ++ private final Field _field; ++ private final long _offset; ++ ++ LongFieldSerializer(Field field) ++ { ++ _field = field; ++ _offset = _unsafe.objectFieldOffset(field); ++ ++ if (_offset == Unsafe.INVALID_FIELD_OFFSET) ++ throw new IllegalStateException(); ++ } ++ ++ final void serialize(AbstractHessianOutput out, Object obj) ++ throws IOException ++ { ++ long value = _unsafe.getLong(obj, _offset); ++ ++ out.writeLong(value); ++ } ++ } ++ ++ final static class FloatFieldSerializer extends FieldSerializer { ++ private final Field _field; ++ private final long _offset; ++ ++ FloatFieldSerializer(Field field) ++ { ++ _field = field; ++ _offset = _unsafe.objectFieldOffset(field); ++ ++ if (_offset == Unsafe.INVALID_FIELD_OFFSET) ++ throw new IllegalStateException(); ++ } ++ ++ final void serialize(AbstractHessianOutput out, Object obj) ++ throws IOException ++ { ++ double value = _unsafe.getFloat(obj, _offset); ++ ++ out.writeDouble(value); ++ } ++ } ++ ++ final static class DoubleFieldSerializer extends FieldSerializer { ++ private final Field _field; ++ private final long _offset; ++ ++ DoubleFieldSerializer(Field field) ++ { ++ _field = field; ++ _offset = _unsafe.objectFieldOffset(field); ++ ++ if (_offset == Unsafe.INVALID_FIELD_OFFSET) ++ throw new IllegalStateException(); ++ } ++ ++ final void serialize(AbstractHessianOutput out, Object obj) ++ throws IOException ++ { ++ double value = _unsafe.getDouble(obj, _offset); ++ ++ out.writeDouble(value); ++ } ++ } ++ ++ final static class StringFieldSerializer extends FieldSerializer { ++ private final Field _field; ++ private final long _offset; ++ ++ StringFieldSerializer(Field field) ++ { ++ _field = field; ++ _offset = _unsafe.objectFieldOffset(field); ++ ++ if (_offset == Unsafe.INVALID_FIELD_OFFSET) ++ throw new IllegalStateException(); ++ } ++ ++ @Override ++ final void serialize(AbstractHessianOutput out, Object obj) ++ throws IOException ++ { ++ String value = (String) _unsafe.getObject(obj, _offset); ++ ++ out.writeString(value); ++ } ++ } ++ ++ final static class DateFieldSerializer extends FieldSerializer { ++ private final Field _field; ++ private final long _offset; ++ ++ DateFieldSerializer(Field field) ++ { ++ _field = field; ++ _offset = _unsafe.objectFieldOffset(field); ++ ++ if (_offset == Unsafe.INVALID_FIELD_OFFSET) ++ throw new IllegalStateException(); ++ } ++ ++ @Override ++ void serialize(AbstractHessianOutput out, Object obj) ++ throws IOException ++ { ++ java.util.Date value ++ = (java.util.Date) _unsafe.getObject(obj, _offset); ++ ++ if (value == null) ++ out.writeNull(); ++ else ++ out.writeUTCDate(value.getTime()); ++ } ++ } ++ ++ static { ++ boolean isEnabled = false; ++ ++ try { ++ Class unsafe = Class.forName("sun.misc.Unsafe"); ++ Field theUnsafe = null; ++ for (Field field : unsafe.getDeclaredFields()) { ++ if (field.getName().equals("theUnsafe")) ++ theUnsafe = field; ++ } ++ ++ if (theUnsafe != null) { ++ theUnsafe.setAccessible(true); ++ _unsafe = (Unsafe) theUnsafe.get(null); ++ } ++ ++ isEnabled = _unsafe != null; ++ ++ String unsafeProp = System.getProperty("com.caucho.hessian.unsafe"); ++ ++ if ("false".equals(unsafeProp)) ++ isEnabled = false; ++ } catch (Throwable e) { ++ log.log(Level.FINER, e.toString(), e); ++ } ++ ++ _isEnabled = isEnabled; ++ } ++ ++} +diff -Npur hessian-4.0.65-src/com/caucho/hessian/io/SerializerFactory.java hessian-4.0.65-fix/com/caucho/hessian/io/SerializerFactory.java +--- hessian-4.0.65-src/com/caucho/hessian/io/SerializerFactory.java 2020-07-23 12:51:28.000000000 +0800 ++++ hessian-4.0.65-fix/com/caucho/hessian/io/SerializerFactory.java 2023-08-15 18:39:22.000000000 +0800 +@@ -1,804 +1,810 @@ +-/* +- * Copyright (c) 2001-2008 Caucho Technology, Inc. All rights reserved. +- * +- * The Apache Software License, Version 1.1 +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions +- * are met: +- * +- * 1. Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * +- * 2. Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in +- * the documentation and/or other materials provided with the +- * distribution. +- * +- * 3. The end-user documentation included with the redistribution, if +- * any, must include the following acknowlegement: +- * "This product includes software developed by the +- * Caucho Technology (http://www.caucho.com/)." +- * Alternately, this acknowlegement may appear in the software itself, +- * if and wherever such third-party acknowlegements normally appear. +- * +- * 4. The names "Burlap", "Resin", and "Caucho" must not be used to +- * endorse or promote products derived from this software without prior +- * written permission. For written permission, please contact +- * info@caucho.com. +- * +- * 5. Products derived from this software may not be called "Resin" +- * nor may "Resin" appear in their names without prior written +- * permission of Caucho Technology. +- * +- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +- * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS +- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +- * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- * +- * @author Scott Ferguson +- */ +- +-package com.caucho.hessian.io; +- +-import java.io.IOException; +-import java.io.InputStream; +-import java.io.Serializable; +-import java.lang.annotation.Annotation; +-import java.lang.ref.SoftReference; +-import java.lang.ref.WeakReference; +-import java.net.InetAddress; +-import java.util.ArrayList; +-import java.util.Calendar; +-import java.util.Collection; +-import java.util.Enumeration; +-import java.util.HashMap; +-import java.util.Iterator; +-import java.util.Map; +-import java.util.WeakHashMap; +-import java.util.concurrent.ConcurrentHashMap; +-import java.util.logging.Level; +-import java.util.logging.Logger; +- +-import com.caucho.burlap.io.BurlapRemoteObject; +- +-/** +- * Factory for returning serialization methods. +- */ +-public class SerializerFactory extends AbstractSerializerFactory +-{ +- private static final Logger log +- = Logger.getLogger(SerializerFactory.class.getName()); +- +- private static final Deserializer OBJECT_DESERIALIZER +- = new BasicDeserializer(BasicDeserializer.OBJECT); +- +- private static final ClassLoader _systemClassLoader; +- +- private static final HashMap _staticTypeMap; +- +- private static final +- WeakHashMap> +- _defaultFactoryRefMap +- = new WeakHashMap>(); +- +- private ContextSerializerFactory _contextFactory; +- private WeakReference _loaderRef; +- +- protected Serializer _defaultSerializer; +- +- // Additional factories +- protected ArrayList _factories = new ArrayList(); +- +- protected CollectionSerializer _collectionSerializer; +- protected MapSerializer _mapSerializer; +- +- private Deserializer _hashMapDeserializer; +- private Deserializer _arrayListDeserializer; +- private Map _cachedSerializerMap; +- private Map _cachedDeserializerMap; +- private HashMap _cachedTypeDeserializerMap; +- +- private boolean _isAllowNonSerializable; +- private boolean _isEnableUnsafeSerializer +- = (UnsafeSerializer.isEnabled() +- && UnsafeDeserializer.isEnabled()); +- +- private FieldDeserializer2Factory _fieldDeserializerFactory; +- +- private ClassFactory _classFactory; +- +- public SerializerFactory() +- { +- this(Thread.currentThread().getContextClassLoader()); +- } +- +- public SerializerFactory(ClassLoader loader) +- { +- _loaderRef = new WeakReference(loader); +- +- _contextFactory = ContextSerializerFactory.create(loader); +- +- if (_isEnableUnsafeSerializer) { +- _fieldDeserializerFactory = new FieldDeserializer2FactoryUnsafe(); +- } +- else { +- _fieldDeserializerFactory = new FieldDeserializer2Factory(); +- } +- } +- +- public static SerializerFactory createDefault() +- { +- ClassLoader loader = Thread.currentThread().getContextClassLoader(); +- +- synchronized (_defaultFactoryRefMap) { +- SoftReference factoryRef +- = _defaultFactoryRefMap.get(loader); +- +- SerializerFactory factory = null; +- +- if (factoryRef != null) +- factory = factoryRef.get(); +- +- if (factory == null) { +- factory = new SerializerFactory(); +- +- factoryRef = new SoftReference(factory); +- +- _defaultFactoryRefMap.put(loader, factoryRef); +- } +- +- return factory; +- } +- } +- +- public ClassLoader getClassLoader() +- { +- return _loaderRef.get(); +- } +- +- /** +- * Set true if the collection serializer should send the java type. +- */ +- public void setSendCollectionType(boolean isSendType) +- { +- if (_collectionSerializer == null) +- _collectionSerializer = new CollectionSerializer(); +- +- _collectionSerializer.setSendJavaType(isSendType); +- +- if (_mapSerializer == null) +- _mapSerializer = new MapSerializer(); +- +- _mapSerializer.setSendJavaType(isSendType); +- } +- +- /** +- * Adds a factory. +- */ +- public void addFactory(AbstractSerializerFactory factory) +- { +- _factories.add(factory); +- } +- +- /** +- * If true, non-serializable objects are allowed. +- */ +- public void setAllowNonSerializable(boolean allow) +- { +- _isAllowNonSerializable = allow; +- } +- +- /** +- * If true, non-serializable objects are allowed. +- */ +- public boolean isAllowNonSerializable() +- { +- return _isAllowNonSerializable; +- } +- +- /** +- * Returns the serializer for a class. +- * +- * @param cl the class of the object that needs to be serialized. +- * +- * @return a serializer object for the serialization. +- */ +- public Serializer getObjectSerializer(Class cl) +- throws HessianProtocolException +- { +- Serializer serializer = getSerializer(cl); +- +- if (serializer instanceof ObjectSerializer) +- return ((ObjectSerializer) serializer).getObjectSerializer(); +- else +- return serializer; +- } +- +- public Class loadSerializedClass(String className) +- throws ClassNotFoundException +- { +- return getClassFactory().load(className); +- } +- +- public ClassFactory getClassFactory() +- { +- synchronized (this) { +- if (_classFactory == null) { +- _classFactory = new ClassFactory(getClassLoader()); +- } +- +- return _classFactory; +- } +- } +- +- public FieldDeserializer2Factory getFieldDeserializerFactory() +- { +- return _fieldDeserializerFactory; +- } +- +- /** +- * Returns the serializer for a class. +- * +- * @param cl the class of the object that needs to be serialized. +- * +- * @return a serializer object for the serialization. +- */ +- public Serializer getSerializer(Class cl) +- throws HessianProtocolException +- { +- Serializer serializer; +- +- if (_cachedSerializerMap != null) { +- serializer = (Serializer) _cachedSerializerMap.get(cl); +- +- if (serializer != null) { +- return serializer; +- } +- } +- +- serializer = loadSerializer(cl); +- +- if (_cachedSerializerMap == null) +- _cachedSerializerMap = new ConcurrentHashMap(8); +- +- _cachedSerializerMap.put(cl, serializer); +- +- return serializer; +- } +- +- protected Serializer loadSerializer(Class cl) +- throws HessianProtocolException +- { +- Serializer serializer = null; +- +- for (int i = 0; +- _factories != null && i < _factories.size(); +- i++) { +- AbstractSerializerFactory factory; +- +- factory = (AbstractSerializerFactory) _factories.get(i); +- +- serializer = factory.getSerializer(cl); +- +- if (serializer != null) +- return serializer; +- } +- +- serializer = _contextFactory.getSerializer(cl.getName()); +- +- if (serializer != null) +- return serializer; +- +- ClassLoader loader = cl.getClassLoader(); +- +- if (loader == null) +- loader = _systemClassLoader; +- +- ContextSerializerFactory factory = null; +- +- factory = ContextSerializerFactory.create(loader); +- +- serializer = factory.getCustomSerializer(cl); +- +- if (serializer != null) { +- return serializer; +- } +- +- if (HessianRemoteObject.class.isAssignableFrom(cl)) { +- return new RemoteSerializer(); +- } +- else if (BurlapRemoteObject.class.isAssignableFrom(cl)) { +- return new RemoteSerializer(); +- } +- else if (InetAddress.class.isAssignableFrom(cl)) { +- return InetAddressSerializer.create(); +- } +- else if (JavaSerializer.getWriteReplace(cl) != null) { +- Serializer baseSerializer = getDefaultSerializer(cl); +- +- return new WriteReplaceSerializer(cl, getClassLoader(), baseSerializer); +- } +- else if (Map.class.isAssignableFrom(cl)) { +- if (_mapSerializer == null) +- _mapSerializer = new MapSerializer(); +- +- return _mapSerializer; +- } +- else if (Collection.class.isAssignableFrom(cl)) { +- if (_collectionSerializer == null) { +- _collectionSerializer = new CollectionSerializer(); +- } +- +- return _collectionSerializer; +- } +- +- else if (cl.isArray()) { +- return new ArraySerializer(); +- } +- +- else if (Throwable.class.isAssignableFrom(cl)) +- return new ThrowableSerializer(getDefaultSerializer(cl)); +- +- else if (InputStream.class.isAssignableFrom(cl)) +- return new InputStreamSerializer(); +- +- else if (Iterator.class.isAssignableFrom(cl)) +- return IteratorSerializer.create(); +- +- else if (Calendar.class.isAssignableFrom(cl)) +- return CalendarSerializer.SER; +- +- else if (Enumeration.class.isAssignableFrom(cl)) +- return EnumerationSerializer.create(); +- +- else if (Enum.class.isAssignableFrom(cl)) +- return new EnumSerializer(cl); +- +- else if (Annotation.class.isAssignableFrom(cl)) +- return new AnnotationSerializer(cl); +- +- return getDefaultSerializer(cl); +- } +- +- /** +- * Returns the default serializer for a class that isn't matched +- * directly. Application can override this method to produce +- * bean-style serialization instead of field serialization. +- * +- * @param cl the class of the object that needs to be serialized. +- * +- * @return a serializer object for the serialization. +- */ +- protected Serializer getDefaultSerializer(Class cl) +- { +- if (_defaultSerializer != null) +- return _defaultSerializer; +- +- if (! Serializable.class.isAssignableFrom(cl) +- && ! _isAllowNonSerializable) { +- throw new IllegalStateException("Serialized class " + cl.getName() + " must implement java.io.Serializable"); +- } +- +- if (_isEnableUnsafeSerializer +- && JavaSerializer.getWriteReplace(cl) == null) { +- return UnsafeSerializer.create(cl); +- } +- else +- return JavaSerializer.create(cl); +- } +- +- /** +- * Returns the deserializer for a class. +- * +- * @param cl the class of the object that needs to be deserialized. +- * +- * @return a deserializer object for the serialization. +- */ +- public Deserializer getDeserializer(Class cl) +- throws HessianProtocolException +- { +- Deserializer deserializer; +- +- if (_cachedDeserializerMap != null) { +- deserializer = (Deserializer) _cachedDeserializerMap.get(cl); +- +- if (deserializer != null) +- return deserializer; +- } +- +- deserializer = loadDeserializer(cl); +- +- if (_cachedDeserializerMap == null) +- _cachedDeserializerMap = new ConcurrentHashMap(8); +- +- _cachedDeserializerMap.put(cl, deserializer); +- +- return deserializer; +- } +- +- protected Deserializer loadDeserializer(Class cl) +- throws HessianProtocolException +- { +- Deserializer deserializer = null; +- +- for (int i = 0; +- deserializer == null && _factories != null && i < _factories.size(); +- i++) { +- AbstractSerializerFactory factory; +- factory = (AbstractSerializerFactory) _factories.get(i); +- +- deserializer = factory.getDeserializer(cl); +- } +- +- if (deserializer != null) +- return deserializer; +- +- // XXX: need test +- deserializer = _contextFactory.getDeserializer(cl.getName()); +- +- if (deserializer != null) +- return deserializer; +- +- ContextSerializerFactory factory = null; +- +- if (cl.getClassLoader() != null) +- factory = ContextSerializerFactory.create(cl.getClassLoader()); +- else +- factory = ContextSerializerFactory.create(_systemClassLoader); +- +- deserializer = factory.getDeserializer(cl.getName()); +- +- if (deserializer != null) +- return deserializer; +- +- deserializer = factory.getCustomDeserializer(cl); +- +- if (deserializer != null) +- return deserializer; +- +- if (Collection.class.isAssignableFrom(cl)) +- deserializer = new CollectionDeserializer(cl); +- +- else if (Map.class.isAssignableFrom(cl)) { +- deserializer = new MapDeserializer(cl); +- } +- else if (Iterator.class.isAssignableFrom(cl)) { +- deserializer = IteratorDeserializer.create(); +- } +- else if (Annotation.class.isAssignableFrom(cl)) { +- deserializer = new AnnotationDeserializer(cl); +- } +- else if (cl.isInterface()) { +- deserializer = new ObjectDeserializer(cl); +- } +- else if (cl.isArray()) { +- deserializer = new ArrayDeserializer(cl.getComponentType()); +- } +- else if (Enumeration.class.isAssignableFrom(cl)) { +- deserializer = EnumerationDeserializer.create(); +- } +- else if (Enum.class.isAssignableFrom(cl)) +- deserializer = new EnumDeserializer(cl); +- +- else if (Class.class.equals(cl)) +- deserializer = new ClassDeserializer(getClassLoader()); +- +- else +- deserializer = getDefaultDeserializer(cl); +- +- return deserializer; +- } +- +- /** +- * Returns a custom serializer the class +- * +- * @param cl the class of the object that needs to be serialized. +- * +- * @return a serializer object for the serialization. +- */ +- protected Deserializer getCustomDeserializer(Class cl) +- { +- try { +- Class serClass = Class.forName(cl.getName() + "HessianDeserializer", +- false, cl.getClassLoader()); +- +- Deserializer ser = (Deserializer) serClass.newInstance(); +- +- return ser; +- } catch (ClassNotFoundException e) { +- log.log(Level.FINEST, e.toString(), e); +- +- return null; +- } catch (Exception e) { +- log.log(Level.FINE, e.toString(), e); +- +- return null; +- } +- } +- +- /** +- * Returns the default serializer for a class that isn't matched +- * directly. Application can override this method to produce +- * bean-style serialization instead of field serialization. +- * +- * @param cl the class of the object that needs to be serialized. +- * +- * @return a serializer object for the serialization. +- */ +- protected Deserializer getDefaultDeserializer(Class cl) +- { +- if (InputStream.class.equals(cl)) +- return InputStreamDeserializer.DESER; +- +- if (_isEnableUnsafeSerializer) { +- return new UnsafeDeserializer(cl, _fieldDeserializerFactory); +- } +- else +- return new JavaDeserializer(cl, _fieldDeserializerFactory); +- } +- +- /** +- * Reads the object as a list. +- */ +- public Object readList(AbstractHessianInput in, int length, String type) +- throws HessianProtocolException, IOException +- { +- Deserializer deserializer = getDeserializer(type); +- +- if (deserializer != null) +- return deserializer.readList(in, length); +- else +- return new CollectionDeserializer(ArrayList.class).readList(in, length); +- } +- +- /** +- * Reads the object as a map. +- */ +- public Object readMap(AbstractHessianInput in, String type) +- throws HessianProtocolException, IOException +- { +- Deserializer deserializer = getDeserializer(type); +- +- if (deserializer != null) +- return deserializer.readMap(in); +- else if (_hashMapDeserializer != null) +- return _hashMapDeserializer.readMap(in); +- else { +- _hashMapDeserializer = new MapDeserializer(HashMap.class); +- +- return _hashMapDeserializer.readMap(in); +- } +- } +- +- /** +- * Reads the object as a map. +- */ +- public Object readObject(AbstractHessianInput in, +- String type, +- String []fieldNames) +- throws HessianProtocolException, IOException +- { +- Deserializer deserializer = getDeserializer(type); +- +- if (deserializer != null) +- return deserializer.readObject(in, fieldNames); +- else if (_hashMapDeserializer != null) +- return _hashMapDeserializer.readObject(in, fieldNames); +- else { +- _hashMapDeserializer = new MapDeserializer(HashMap.class); +- +- return _hashMapDeserializer.readObject(in, fieldNames); +- } +- } +- +- /** +- * Reads the object as a map. +- */ +- public Deserializer getObjectDeserializer(String type, Class cl) +- throws HessianProtocolException +- { +- Deserializer reader = getObjectDeserializer(type); +- +- if (cl == null +- || cl.equals(reader.getType()) +- || cl.isAssignableFrom(reader.getType()) +- || reader.isReadResolve() +- || HessianHandle.class.isAssignableFrom(reader.getType())) { +- return reader; +- } +- +- if (log.isLoggable(Level.FINE)) { +- log.fine("hessian: expected deserializer '" + cl.getName() + "' at '" + type + "' (" +- + reader.getType().getName() + ")"); +- } +- +- return getDeserializer(cl); +- } +- +- /** +- * Reads the object as a map. +- */ +- public Deserializer getObjectDeserializer(String type) +- throws HessianProtocolException +- { +- Deserializer deserializer = getDeserializer(type); +- +- if (deserializer != null) +- return deserializer; +- else if (_hashMapDeserializer != null) +- return _hashMapDeserializer; +- else { +- _hashMapDeserializer = new MapDeserializer(HashMap.class); +- +- return _hashMapDeserializer; +- } +- } +- +- /** +- * Reads the object as a map. +- */ +- public Deserializer getListDeserializer(String type, Class cl) +- throws HessianProtocolException +- { +- Deserializer reader = getListDeserializer(type); +- +- if (cl == null +- || cl.equals(reader.getType()) +- || cl.isAssignableFrom(reader.getType())) { +- return reader; +- } +- +- if (log.isLoggable(Level.FINE)) { +- log.fine("hessian: expected '" + cl.getName() + "' at '" + type + "' (" +- + reader.getType().getName() + ")"); +- } +- +- return getDeserializer(cl); +- } +- +- /** +- * Reads the object as a map. +- */ +- public Deserializer getListDeserializer(String type) +- throws HessianProtocolException +- { +- Deserializer deserializer = getDeserializer(type); +- +- if (deserializer != null) +- return deserializer; +- else if (_arrayListDeserializer != null) +- return _arrayListDeserializer; +- else { +- _arrayListDeserializer = new CollectionDeserializer(ArrayList.class); +- +- return _arrayListDeserializer; +- } +- } +- +- /** +- * Returns a deserializer based on a string type. +- */ +- public Deserializer getDeserializer(String type) +- throws HessianProtocolException +- { +- if (type == null || type.equals("")) +- return null; +- +- Deserializer deserializer; +- +- if (_cachedTypeDeserializerMap != null) { +- synchronized (_cachedTypeDeserializerMap) { +- deserializer = (Deserializer) _cachedTypeDeserializerMap.get(type); +- } +- +- if (deserializer != null) +- return deserializer; +- } +- +- +- deserializer = (Deserializer) _staticTypeMap.get(type); +- if (deserializer != null) +- return deserializer; +- +- if (type.startsWith("[")) { +- Deserializer subDeserializer = getDeserializer(type.substring(1)); +- +- if (subDeserializer != null) +- deserializer = new ArrayDeserializer(subDeserializer.getType()); +- else +- deserializer = new ArrayDeserializer(Object.class); +- } +- else { +- try { +- //Class cl = Class.forName(type, false, getClassLoader()); +- +- Class cl = loadSerializedClass(type); +- +- deserializer = getDeserializer(cl); +- } catch (Exception e) { +- log.warning("Hessian/Burlap: '" + type + "' is an unknown class in " + getClassLoader() + ":\n" + e); +- +- log.log(Level.FINER, e.toString(), e); +- } +- } +- +- if (deserializer != null) { +- if (_cachedTypeDeserializerMap == null) +- _cachedTypeDeserializerMap = new HashMap(8); +- +- synchronized (_cachedTypeDeserializerMap) { +- _cachedTypeDeserializerMap.put(type, deserializer); +- } +- } +- +- return deserializer; +- } +- +- private static void addBasic(Class cl, String typeName, int type) +- { +- Deserializer deserializer = new BasicDeserializer(type); +- +- _staticTypeMap.put(typeName, deserializer); +- } +- +- static { +- _staticTypeMap = new HashMap(); +- +- addBasic(void.class, "void", BasicSerializer.NULL); +- +- addBasic(Boolean.class, "boolean", BasicSerializer.BOOLEAN); +- addBasic(Byte.class, "byte", BasicSerializer.BYTE); +- addBasic(Short.class, "short", BasicSerializer.SHORT); +- addBasic(Integer.class, "int", BasicSerializer.INTEGER); +- addBasic(Long.class, "long", BasicSerializer.LONG); +- addBasic(Float.class, "float", BasicSerializer.FLOAT); +- addBasic(Double.class, "double", BasicSerializer.DOUBLE); +- addBasic(Character.class, "char", BasicSerializer.CHARACTER_OBJECT); +- addBasic(String.class, "string", BasicSerializer.STRING); +- addBasic(StringBuilder.class, "string", BasicSerializer.STRING_BUILDER); +- addBasic(Object.class, "object", BasicSerializer.OBJECT); +- addBasic(java.util.Date.class, "date", BasicSerializer.DATE); +- +- addBasic(boolean.class, "boolean", BasicSerializer.BOOLEAN); +- addBasic(byte.class, "byte", BasicSerializer.BYTE); +- addBasic(short.class, "short", BasicSerializer.SHORT); +- addBasic(int.class, "int", BasicSerializer.INTEGER); +- addBasic(long.class, "long", BasicSerializer.LONG); +- addBasic(float.class, "float", BasicSerializer.FLOAT); +- addBasic(double.class, "double", BasicSerializer.DOUBLE); +- addBasic(char.class, "char", BasicSerializer.CHARACTER); +- +- addBasic(boolean[].class, "[boolean", BasicSerializer.BOOLEAN_ARRAY); +- addBasic(byte[].class, "[byte", BasicSerializer.BYTE_ARRAY); +- addBasic(short[].class, "[short", BasicSerializer.SHORT_ARRAY); +- addBasic(int[].class, "[int", BasicSerializer.INTEGER_ARRAY); +- addBasic(long[].class, "[long", BasicSerializer.LONG_ARRAY); +- addBasic(float[].class, "[float", BasicSerializer.FLOAT_ARRAY); +- addBasic(double[].class, "[double", BasicSerializer.DOUBLE_ARRAY); +- addBasic(char[].class, "[char", BasicSerializer.CHARACTER_ARRAY); +- addBasic(String[].class, "[string", BasicSerializer.STRING_ARRAY); +- addBasic(Object[].class, "[object", BasicSerializer.OBJECT_ARRAY); +- +- Deserializer objectDeserializer = new JavaDeserializer(Object.class, new FieldDeserializer2Factory()); +- _staticTypeMap.put("object", objectDeserializer); +- _staticTypeMap.put(HessianRemote.class.getName(), +- RemoteDeserializer.DESER); +- +- +- ClassLoader systemClassLoader = null; +- try { +- systemClassLoader = ClassLoader.getSystemClassLoader(); +- } catch (Exception e) { +- } +- +- _systemClassLoader = systemClassLoader; +- } +-} ++/* ++ * Copyright (c) 2001-2008 Caucho Technology, Inc. All rights reserved. ++ * ++ * The Apache Software License, Version 1.1 ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * 3. The end-user documentation included with the redistribution, if ++ * any, must include the following acknowlegement: ++ * "This product includes software developed by the ++ * Caucho Technology (http://www.caucho.com/)." ++ * Alternately, this acknowlegement may appear in the software itself, ++ * if and wherever such third-party acknowlegements normally appear. ++ * ++ * 4. The names "Burlap", "Resin", and "Caucho" must not be used to ++ * endorse or promote products derived from this software without prior ++ * written permission. For written permission, please contact ++ * info@caucho.com. ++ * ++ * 5. Products derived from this software may not be called "Resin" ++ * nor may "Resin" appear in their names without prior written ++ * permission of Caucho Technology. ++ * ++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED ++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++ * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS ++ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, ++ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT ++ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ++ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE ++ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN ++ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * @author Scott Ferguson ++ */ ++ ++package com.caucho.hessian.io; ++ ++import java.io.IOException; ++import java.io.InputStream; ++import java.io.Serializable; ++import java.lang.annotation.Annotation; ++import java.lang.ref.SoftReference; ++import java.lang.ref.WeakReference; ++import java.net.InetAddress; ++import java.math.BigDecimal; ++import java.util.ArrayList; ++import java.util.Calendar; ++import java.util.Collection; ++import java.util.Enumeration; ++import java.util.HashMap; ++import java.util.Iterator; ++import java.util.Map; ++import java.util.WeakHashMap; ++import java.util.concurrent.ConcurrentHashMap; ++import java.util.logging.Level; ++import java.util.logging.Logger; ++ ++import com.caucho.burlap.io.BurlapRemoteObject; ++ ++/** ++ * Factory for returning serialization methods. ++ */ ++public class SerializerFactory extends AbstractSerializerFactory ++{ ++ private static final Logger log ++ = Logger.getLogger(SerializerFactory.class.getName()); ++ ++ private static final Deserializer OBJECT_DESERIALIZER ++ = new BasicDeserializer(BasicDeserializer.OBJECT); ++ ++ private static final ClassLoader _systemClassLoader; ++ ++ private static final HashMap _staticTypeMap; ++ ++ private static final ++ WeakHashMap> ++ _defaultFactoryRefMap ++ = new WeakHashMap>(); ++ ++ private ContextSerializerFactory _contextFactory; ++ private WeakReference _loaderRef; ++ ++ protected Serializer _defaultSerializer; ++ ++ // Additional factories ++ protected ArrayList _factories = new ArrayList(); ++ ++ protected CollectionSerializer _collectionSerializer; ++ protected MapSerializer _mapSerializer; ++ ++ private Deserializer _hashMapDeserializer; ++ private Deserializer _arrayListDeserializer; ++ private Map _cachedSerializerMap; ++ private Map _cachedDeserializerMap; ++ private HashMap _cachedTypeDeserializerMap; ++ ++ private boolean _isAllowNonSerializable; ++ private boolean _isEnableUnsafeSerializer ++ = (UnsafeSerializer.isEnabled() ++ && UnsafeDeserializer.isEnabled()); ++ ++ private FieldDeserializer2Factory _fieldDeserializerFactory; ++ ++ private ClassFactory _classFactory; ++ ++ public SerializerFactory() ++ { ++ this(Thread.currentThread().getContextClassLoader()); ++ } ++ ++ public SerializerFactory(ClassLoader loader) ++ { ++ _loaderRef = new WeakReference(loader); ++ ++ _contextFactory = ContextSerializerFactory.create(loader); ++ ++ if (_isEnableUnsafeSerializer) { ++ _fieldDeserializerFactory = new FieldDeserializer2FactoryUnsafe(); ++ } ++ else { ++ _fieldDeserializerFactory = new FieldDeserializer2Factory(); ++ } ++ } ++ ++ public static SerializerFactory createDefault() ++ { ++ ClassLoader loader = Thread.currentThread().getContextClassLoader(); ++ ++ synchronized (_defaultFactoryRefMap) { ++ SoftReference factoryRef ++ = _defaultFactoryRefMap.get(loader); ++ ++ SerializerFactory factory = null; ++ ++ if (factoryRef != null) ++ factory = factoryRef.get(); ++ ++ if (factory == null) { ++ factory = new SerializerFactory(); ++ ++ factoryRef = new SoftReference(factory); ++ ++ _defaultFactoryRefMap.put(loader, factoryRef); ++ } ++ ++ return factory; ++ } ++ } ++ ++ public ClassLoader getClassLoader() ++ { ++ return _loaderRef.get(); ++ } ++ ++ /** ++ * Set true if the collection serializer should send the java type. ++ */ ++ public void setSendCollectionType(boolean isSendType) ++ { ++ if (_collectionSerializer == null) ++ _collectionSerializer = new CollectionSerializer(); ++ ++ _collectionSerializer.setSendJavaType(isSendType); ++ ++ if (_mapSerializer == null) ++ _mapSerializer = new MapSerializer(); ++ ++ _mapSerializer.setSendJavaType(isSendType); ++ } ++ ++ /** ++ * Adds a factory. ++ */ ++ public void addFactory(AbstractSerializerFactory factory) ++ { ++ _factories.add(factory); ++ } ++ ++ /** ++ * If true, non-serializable objects are allowed. ++ */ ++ public void setAllowNonSerializable(boolean allow) ++ { ++ _isAllowNonSerializable = allow; ++ } ++ ++ /** ++ * If true, non-serializable objects are allowed. ++ */ ++ public boolean isAllowNonSerializable() ++ { ++ return _isAllowNonSerializable; ++ } ++ ++ /** ++ * Returns the serializer for a class. ++ * ++ * @param cl the class of the object that needs to be serialized. ++ * ++ * @return a serializer object for the serialization. ++ */ ++ public Serializer getObjectSerializer(Class cl) ++ throws HessianProtocolException ++ { ++ Serializer serializer = getSerializer(cl); ++ ++ if (serializer instanceof ObjectSerializer) ++ return ((ObjectSerializer) serializer).getObjectSerializer(); ++ else ++ return serializer; ++ } ++ ++ public Class loadSerializedClass(String className) ++ throws ClassNotFoundException ++ { ++ return getClassFactory().load(className); ++ } ++ ++ public ClassFactory getClassFactory() ++ { ++ synchronized (this) { ++ if (_classFactory == null) { ++ _classFactory = new ClassFactory(getClassLoader()); ++ } ++ ++ return _classFactory; ++ } ++ } ++ ++ public FieldDeserializer2Factory getFieldDeserializerFactory() ++ { ++ return _fieldDeserializerFactory; ++ } ++ ++ /** ++ * Returns the serializer for a class. ++ * ++ * @param cl the class of the object that needs to be serialized. ++ * ++ * @return a serializer object for the serialization. ++ */ ++ public Serializer getSerializer(Class cl) ++ throws HessianProtocolException ++ { ++ Serializer serializer; ++ ++ if (_cachedSerializerMap != null) { ++ serializer = (Serializer) _cachedSerializerMap.get(cl); ++ ++ if (serializer != null) { ++ return serializer; ++ } ++ } ++ ++ serializer = loadSerializer(cl); ++ ++ if (_cachedSerializerMap == null) ++ _cachedSerializerMap = new ConcurrentHashMap(8); ++ ++ _cachedSerializerMap.put(cl, serializer); ++ ++ return serializer; ++ } ++ ++ protected Serializer loadSerializer(Class cl) ++ throws HessianProtocolException ++ { ++ Serializer serializer = null; ++ ++ for (int i = 0; ++ _factories != null && i < _factories.size(); ++ i++) { ++ AbstractSerializerFactory factory; ++ ++ factory = (AbstractSerializerFactory) _factories.get(i); ++ ++ serializer = factory.getSerializer(cl); ++ ++ if (serializer != null) ++ return serializer; ++ } ++ ++ serializer = _contextFactory.getSerializer(cl.getName()); ++ ++ if (serializer != null) ++ return serializer; ++ ++ ClassLoader loader = cl.getClassLoader(); ++ ++ if (loader == null) ++ loader = _systemClassLoader; ++ ++ ContextSerializerFactory factory = null; ++ ++ factory = ContextSerializerFactory.create(loader); ++ ++ serializer = factory.getCustomSerializer(cl); ++ ++ if (serializer != null) { ++ return serializer; ++ } ++ ++ if (HessianRemoteObject.class.isAssignableFrom(cl)) { ++ return new RemoteSerializer(); ++ } ++ else if (BurlapRemoteObject.class.isAssignableFrom(cl)) { ++ return new RemoteSerializer(); ++ } ++ else if (InetAddress.class.isAssignableFrom(cl)) { ++ return InetAddressSerializer.create(); ++ } ++ else if (JavaSerializer.getWriteReplace(cl) != null) { ++ Serializer baseSerializer = getDefaultSerializer(cl); ++ ++ return new WriteReplaceSerializer(cl, getClassLoader(), baseSerializer); ++ } ++ else if (Map.class.isAssignableFrom(cl)) { ++ if (_mapSerializer == null) ++ _mapSerializer = new MapSerializer(); ++ ++ return _mapSerializer; ++ } ++ else if (Collection.class.isAssignableFrom(cl)) { ++ if (_collectionSerializer == null) { ++ _collectionSerializer = new CollectionSerializer(); ++ } ++ ++ return _collectionSerializer; ++ } ++ ++ else if (cl.isArray()) { ++ return new ArraySerializer(); ++ } ++ ++ else if (Throwable.class.isAssignableFrom(cl)) ++ return new ThrowableSerializer(getDefaultSerializer(cl)); ++ ++ else if (InputStream.class.isAssignableFrom(cl)) ++ return new InputStreamSerializer(); ++ ++ else if (Iterator.class.isAssignableFrom(cl)) ++ return IteratorSerializer.create(); ++ ++ else if (Calendar.class.isAssignableFrom(cl)) ++ return CalendarSerializer.SER; ++ ++ else if (Enumeration.class.isAssignableFrom(cl)) ++ return EnumerationSerializer.create(); ++ ++ else if (Enum.class.isAssignableFrom(cl)) ++ return new EnumSerializer(cl); ++ ++ else if (Annotation.class.isAssignableFrom(cl)) ++ return new AnnotationSerializer(cl); ++ ++ else if (BigDecimal.class.isAssignableFrom(cl)) ++ return new NonTransientUnsafeSerializer(cl); ++ else ++ return getDefaultSerializer(cl); ++ } ++ ++ /** ++ * Returns the default serializer for a class that isn't matched ++ * directly. Application can override this method to produce ++ * bean-style serialization instead of field serialization. ++ * ++ * @param cl the class of the object that needs to be serialized. ++ * ++ * @return a serializer object for the serialization. ++ */ ++ protected Serializer getDefaultSerializer(Class cl) ++ { ++ if (_defaultSerializer != null) ++ return _defaultSerializer; ++ ++ if (! Serializable.class.isAssignableFrom(cl) ++ && ! _isAllowNonSerializable) { ++ throw new IllegalStateException("Serialized class " + cl.getName() + " must implement java.io.Serializable"); ++ } ++ ++ if (_isEnableUnsafeSerializer ++ && JavaSerializer.getWriteReplace(cl) == null) { ++ return UnsafeSerializer.create(cl); ++ } ++ else ++ return JavaSerializer.create(cl); ++ } ++ ++ /** ++ * Returns the deserializer for a class. ++ * ++ * @param cl the class of the object that needs to be deserialized. ++ * ++ * @return a deserializer object for the serialization. ++ */ ++ public Deserializer getDeserializer(Class cl) ++ throws HessianProtocolException ++ { ++ Deserializer deserializer; ++ ++ if (_cachedDeserializerMap != null) { ++ deserializer = (Deserializer) _cachedDeserializerMap.get(cl); ++ ++ if (deserializer != null) ++ return deserializer; ++ } ++ ++ deserializer = loadDeserializer(cl); ++ ++ if (_cachedDeserializerMap == null) ++ _cachedDeserializerMap = new ConcurrentHashMap(8); ++ ++ _cachedDeserializerMap.put(cl, deserializer); ++ ++ return deserializer; ++ } ++ ++ protected Deserializer loadDeserializer(Class cl) ++ throws HessianProtocolException ++ { ++ Deserializer deserializer = null; ++ ++ for (int i = 0; ++ deserializer == null && _factories != null && i < _factories.size(); ++ i++) { ++ AbstractSerializerFactory factory; ++ factory = (AbstractSerializerFactory) _factories.get(i); ++ ++ deserializer = factory.getDeserializer(cl); ++ } ++ ++ if (deserializer != null) ++ return deserializer; ++ ++ // XXX: need test ++ deserializer = _contextFactory.getDeserializer(cl.getName()); ++ ++ if (deserializer != null) ++ return deserializer; ++ ++ ContextSerializerFactory factory = null; ++ ++ if (cl.getClassLoader() != null) ++ factory = ContextSerializerFactory.create(cl.getClassLoader()); ++ else ++ factory = ContextSerializerFactory.create(_systemClassLoader); ++ ++ deserializer = factory.getDeserializer(cl.getName()); ++ ++ if (deserializer != null) ++ return deserializer; ++ ++ deserializer = factory.getCustomDeserializer(cl); ++ ++ if (deserializer != null) ++ return deserializer; ++ ++ if (Collection.class.isAssignableFrom(cl)) ++ deserializer = new CollectionDeserializer(cl); ++ ++ else if (Map.class.isAssignableFrom(cl)) { ++ deserializer = new MapDeserializer(cl); ++ } ++ else if (Iterator.class.isAssignableFrom(cl)) { ++ deserializer = IteratorDeserializer.create(); ++ } ++ else if (Annotation.class.isAssignableFrom(cl)) { ++ deserializer = new AnnotationDeserializer(cl); ++ } ++ else if (cl.isInterface()) { ++ deserializer = new ObjectDeserializer(cl); ++ } ++ else if (cl.isArray()) { ++ deserializer = new ArrayDeserializer(cl.getComponentType()); ++ } ++ else if (Enumeration.class.isAssignableFrom(cl)) { ++ deserializer = EnumerationDeserializer.create(); ++ } ++ else if (Enum.class.isAssignableFrom(cl)){ ++ deserializer = new EnumDeserializer(cl); ++ } ++ else if (Class.class.equals(cl)) ++ deserializer = new ClassDeserializer(getClassLoader()); ++ ++ else if (BigDecimal.class.equals(cl)) ++ deserializer = new NonTransientUnsafeDeserializer(cl); ++ else ++ deserializer = getDefaultDeserializer(cl); ++ ++ return deserializer; ++ } ++ ++ /** ++ * Returns a custom serializer the class ++ * ++ * @param cl the class of the object that needs to be serialized. ++ * ++ * @return a serializer object for the serialization. ++ */ ++ protected Deserializer getCustomDeserializer(Class cl) ++ { ++ try { ++ Class serClass = Class.forName(cl.getName() + "HessianDeserializer", ++ false, cl.getClassLoader()); ++ ++ Deserializer ser = (Deserializer) serClass.newInstance(); ++ ++ return ser; ++ } catch (ClassNotFoundException e) { ++ log.log(Level.FINEST, e.toString(), e); ++ ++ return null; ++ } catch (Exception e) { ++ log.log(Level.FINE, e.toString(), e); ++ ++ return null; ++ } ++ } ++ ++ /** ++ * Returns the default serializer for a class that isn't matched ++ * directly. Application can override this method to produce ++ * bean-style serialization instead of field serialization. ++ * ++ * @param cl the class of the object that needs to be serialized. ++ * ++ * @return a serializer object for the serialization. ++ */ ++ protected Deserializer getDefaultDeserializer(Class cl) ++ { ++ if (InputStream.class.equals(cl)) ++ return InputStreamDeserializer.DESER; ++ ++ if (_isEnableUnsafeSerializer) { ++ return new UnsafeDeserializer(cl, _fieldDeserializerFactory); ++ } ++ else ++ return new JavaDeserializer(cl, _fieldDeserializerFactory); ++ } ++ ++ /** ++ * Reads the object as a list. ++ */ ++ public Object readList(AbstractHessianInput in, int length, String type) ++ throws HessianProtocolException, IOException ++ { ++ Deserializer deserializer = getDeserializer(type); ++ ++ if (deserializer != null) ++ return deserializer.readList(in, length); ++ else ++ return new CollectionDeserializer(ArrayList.class).readList(in, length); ++ } ++ ++ /** ++ * Reads the object as a map. ++ */ ++ public Object readMap(AbstractHessianInput in, String type) ++ throws HessianProtocolException, IOException ++ { ++ Deserializer deserializer = getDeserializer(type); ++ ++ if (deserializer != null) ++ return deserializer.readMap(in); ++ else if (_hashMapDeserializer != null) ++ return _hashMapDeserializer.readMap(in); ++ else { ++ _hashMapDeserializer = new MapDeserializer(HashMap.class); ++ ++ return _hashMapDeserializer.readMap(in); ++ } ++ } ++ ++ /** ++ * Reads the object as a map. ++ */ ++ public Object readObject(AbstractHessianInput in, ++ String type, ++ String []fieldNames) ++ throws HessianProtocolException, IOException ++ { ++ Deserializer deserializer = getDeserializer(type); ++ ++ if (deserializer != null) ++ return deserializer.readObject(in, fieldNames); ++ else if (_hashMapDeserializer != null) ++ return _hashMapDeserializer.readObject(in, fieldNames); ++ else { ++ _hashMapDeserializer = new MapDeserializer(HashMap.class); ++ ++ return _hashMapDeserializer.readObject(in, fieldNames); ++ } ++ } ++ ++ /** ++ * Reads the object as a map. ++ */ ++ public Deserializer getObjectDeserializer(String type, Class cl) ++ throws HessianProtocolException ++ { ++ Deserializer reader = getObjectDeserializer(type); ++ ++ if (cl == null ++ || cl.equals(reader.getType()) ++ || cl.isAssignableFrom(reader.getType()) ++ || reader.isReadResolve() ++ || HessianHandle.class.isAssignableFrom(reader.getType())) { ++ return reader; ++ } ++ ++ if (log.isLoggable(Level.FINE)) { ++ log.fine("hessian: expected deserializer '" + cl.getName() + "' at '" + type + "' (" ++ + reader.getType().getName() + ")"); ++ } ++ ++ return getDeserializer(cl); ++ } ++ ++ /** ++ * Reads the object as a map. ++ */ ++ public Deserializer getObjectDeserializer(String type) ++ throws HessianProtocolException ++ { ++ Deserializer deserializer = getDeserializer(type); ++ ++ if (deserializer != null) ++ return deserializer; ++ else if (_hashMapDeserializer != null) ++ return _hashMapDeserializer; ++ else { ++ _hashMapDeserializer = new MapDeserializer(HashMap.class); ++ ++ return _hashMapDeserializer; ++ } ++ } ++ ++ /** ++ * Reads the object as a map. ++ */ ++ public Deserializer getListDeserializer(String type, Class cl) ++ throws HessianProtocolException ++ { ++ Deserializer reader = getListDeserializer(type); ++ ++ if (cl == null ++ || cl.equals(reader.getType()) ++ || cl.isAssignableFrom(reader.getType())) { ++ return reader; ++ } ++ ++ if (log.isLoggable(Level.FINE)) { ++ log.fine("hessian: expected '" + cl.getName() + "' at '" + type + "' (" ++ + reader.getType().getName() + ")"); ++ } ++ ++ return getDeserializer(cl); ++ } ++ ++ /** ++ * Reads the object as a map. ++ */ ++ public Deserializer getListDeserializer(String type) ++ throws HessianProtocolException ++ { ++ Deserializer deserializer = getDeserializer(type); ++ ++ if (deserializer != null) ++ return deserializer; ++ else if (_arrayListDeserializer != null) ++ return _arrayListDeserializer; ++ else { ++ _arrayListDeserializer = new CollectionDeserializer(ArrayList.class); ++ ++ return _arrayListDeserializer; ++ } ++ } ++ ++ /** ++ * Returns a deserializer based on a string type. ++ */ ++ public Deserializer getDeserializer(String type) ++ throws HessianProtocolException ++ { ++ if (type == null || type.equals("")) ++ return null; ++ ++ Deserializer deserializer; ++ ++ if (_cachedTypeDeserializerMap != null) { ++ synchronized (_cachedTypeDeserializerMap) { ++ deserializer = (Deserializer) _cachedTypeDeserializerMap.get(type); ++ } ++ ++ if (deserializer != null) ++ return deserializer; ++ } ++ ++ ++ deserializer = (Deserializer) _staticTypeMap.get(type); ++ if (deserializer != null) ++ return deserializer; ++ ++ if (type.startsWith("[")) { ++ Deserializer subDeserializer = getDeserializer(type.substring(1)); ++ ++ if (subDeserializer != null) ++ deserializer = new ArrayDeserializer(subDeserializer.getType()); ++ else ++ deserializer = new ArrayDeserializer(Object.class); ++ } ++ else { ++ try { ++ //Class cl = Class.forName(type, false, getClassLoader()); ++ ++ Class cl = loadSerializedClass(type); ++ ++ deserializer = getDeserializer(cl); ++ } catch (Exception e) { ++ log.warning("Hessian/Burlap: '" + type + "' is an unknown class in " + getClassLoader() + ":\n" + e); ++ ++ log.log(Level.FINER, e.toString(), e); ++ } ++ } ++ ++ if (deserializer != null) { ++ if (_cachedTypeDeserializerMap == null) ++ _cachedTypeDeserializerMap = new HashMap(8); ++ ++ synchronized (_cachedTypeDeserializerMap) { ++ _cachedTypeDeserializerMap.put(type, deserializer); ++ } ++ } ++ ++ return deserializer; ++ } ++ ++ private static void addBasic(Class cl, String typeName, int type) ++ { ++ Deserializer deserializer = new BasicDeserializer(type); ++ ++ _staticTypeMap.put(typeName, deserializer); ++ } ++ ++ static { ++ _staticTypeMap = new HashMap(); ++ ++ addBasic(void.class, "void", BasicSerializer.NULL); ++ ++ addBasic(Boolean.class, "boolean", BasicSerializer.BOOLEAN); ++ addBasic(Byte.class, "byte", BasicSerializer.BYTE); ++ addBasic(Short.class, "short", BasicSerializer.SHORT); ++ addBasic(Integer.class, "int", BasicSerializer.INTEGER); ++ addBasic(Long.class, "long", BasicSerializer.LONG); ++ addBasic(Float.class, "float", BasicSerializer.FLOAT); ++ addBasic(Double.class, "double", BasicSerializer.DOUBLE); ++ addBasic(Character.class, "char", BasicSerializer.CHARACTER_OBJECT); ++ addBasic(String.class, "string", BasicSerializer.STRING); ++ addBasic(StringBuilder.class, "string", BasicSerializer.STRING_BUILDER); ++ addBasic(Object.class, "object", BasicSerializer.OBJECT); ++ addBasic(java.util.Date.class, "date", BasicSerializer.DATE); ++ ++ addBasic(boolean.class, "boolean", BasicSerializer.BOOLEAN); ++ addBasic(byte.class, "byte", BasicSerializer.BYTE); ++ addBasic(short.class, "short", BasicSerializer.SHORT); ++ addBasic(int.class, "int", BasicSerializer.INTEGER); ++ addBasic(long.class, "long", BasicSerializer.LONG); ++ addBasic(float.class, "float", BasicSerializer.FLOAT); ++ addBasic(double.class, "double", BasicSerializer.DOUBLE); ++ addBasic(char.class, "char", BasicSerializer.CHARACTER); ++ ++ addBasic(boolean[].class, "[boolean", BasicSerializer.BOOLEAN_ARRAY); ++ addBasic(byte[].class, "[byte", BasicSerializer.BYTE_ARRAY); ++ addBasic(short[].class, "[short", BasicSerializer.SHORT_ARRAY); ++ addBasic(int[].class, "[int", BasicSerializer.INTEGER_ARRAY); ++ addBasic(long[].class, "[long", BasicSerializer.LONG_ARRAY); ++ addBasic(float[].class, "[float", BasicSerializer.FLOAT_ARRAY); ++ addBasic(double[].class, "[double", BasicSerializer.DOUBLE_ARRAY); ++ addBasic(char[].class, "[char", BasicSerializer.CHARACTER_ARRAY); ++ addBasic(String[].class, "[string", BasicSerializer.STRING_ARRAY); ++ addBasic(Object[].class, "[object", BasicSerializer.OBJECT_ARRAY); ++ ++ Deserializer objectDeserializer = new JavaDeserializer(Object.class, new FieldDeserializer2Factory()); ++ _staticTypeMap.put("object", objectDeserializer); ++ _staticTypeMap.put(HessianRemote.class.getName(), ++ RemoteDeserializer.DESER); ++ ++ ++ ClassLoader systemClassLoader = null; ++ try { ++ systemClassLoader = ClassLoader.getSystemClassLoader(); ++ } catch (Exception e) { ++ } ++ ++ _systemClassLoader = systemClassLoader; ++ } ++} +diff -Npur hessian-4.0.65-src/com/caucho/hessian/server/HessianDispatcher.java hessian-4.0.65-fix/com/caucho/hessian/server/HessianDispatcher.java +--- hessian-4.0.65-src/com/caucho/hessian/server/HessianDispatcher.java 1970-01-01 08:00:00.000000000 +0800 ++++ hessian-4.0.65-fix/com/caucho/hessian/server/HessianDispatcher.java 2023-08-15 18:39:22.000000000 +0800 +@@ -0,0 +1,337 @@ ++ ++package com.caucho.hessian.server; ++ ++import java.io.IOException; ++import java.io.InputStream; ++import java.io.OutputStream; ++import java.io.PrintWriter; ++import java.io.Writer; ++import java.util.Map; ++import java.util.Properties; ++import java.util.concurrent.ConcurrentHashMap; ++import java.util.logging.Logger; ++ ++import javax.servlet.GenericServlet; ++import javax.servlet.Servlet; ++import javax.servlet.ServletConfig; ++import javax.servlet.ServletException; ++import javax.servlet.ServletRequest; ++import javax.servlet.ServletResponse; ++import javax.servlet.http.HttpServletRequest; ++import javax.servlet.http.HttpServletResponse; ++ ++import org.springframework.context.ApplicationContext; ++import org.springframework.web.context.support.WebApplicationContextUtils; ++ ++import com.caucho.hessian.io.Hessian2Input; ++import com.caucho.hessian.io.SerializerFactory; ++import com.caucho.services.server.Service; ++import com.caucho.services.server.ServiceContext; ++ ++ ++public class HessianDispatcher extends GenericServlet ++{ ++ ++ ++ private static final long serialVersionUID = -8611469561907416355L; ++ ++ private SerializerFactory _serializerFactory; ++ ++ private static final String SERVICE_FILE_PATH = "config-file"; ++ ++ private static Map registry = new ConcurrentHashMap(); ++ ++ private static Properties props = new Properties(); ++ ++ public HessianDispatcher() ++ { ++ } ++ ++ public String getServletInfo() ++ { ++ return "Hessian Dispatcher"; ++ } ++ ++ /** ++ * Sets the serializer factory. ++ */ ++ public void setSerializerFactory(SerializerFactory factory) ++ { ++ _serializerFactory = factory; ++ } ++ ++ /** ++ * Gets the serializer factory. ++ */ ++ public SerializerFactory getSerializerFactory() ++ { ++ if (_serializerFactory == null) ++ _serializerFactory = new SerializerFactory(); ++ ++ return _serializerFactory; ++ } ++ ++ /** ++ * Sets the serializer send collection java type. ++ */ ++ public void setSendCollectionType(boolean sendType) ++ { ++ getSerializerFactory().setSendCollectionType(sendType); ++ } ++ ++ /** ++ * Initialize the service, including the service object. ++ */ ++ public void init(ServletConfig config) throws ServletException ++ { ++ super.init(config); ++ ++ try ++ { ++ String serviceConfigFile = getInitParameter(SERVICE_FILE_PATH); ++ ++ if (null == serviceConfigFile) ++ { ++ throw new ServletException( ++ "Hessian service registry file path must be set in classpath when using 'HessianDispatcher'"); ++ } ++ ++ props.load(this.getClass().getClassLoader() ++ .getResourceAsStream(serviceConfigFile)); ++ } ++ ++ catch (Exception e) ++ { ++ throw new ServletException(e); ++ } ++ } ++ ++ private Class loadClass(String className) throws ClassNotFoundException ++ { ++ ClassLoader loader = getContextClassLoader(); ++ ++ if (loader != null) ++ return Class.forName(className, false, loader); ++ else ++ return Class.forName(className); ++ } ++ ++ protected ClassLoader getContextClassLoader() ++ { ++ return Thread.currentThread().getContextClassLoader(); ++ } ++ ++ private void init(Object service) throws ServletException ++ { ++ if (!this.getClass().equals(HessianDispatcher.class)) ++ { ++ } ++ else if (service instanceof Service) ++ ((Service) service).init(getServletConfig()); ++ else if (service instanceof Servlet) ++ ((Servlet) service).init(getServletConfig()); ++ } ++ ++ /** ++ * Execute a request. The path-info of the request selects the bean. Once ++ * the bean's selected, it will be applied. ++ */ ++ public void service(ServletRequest request, ServletResponse response) ++ throws IOException, ServletException ++ { ++ HttpServletRequest req = (HttpServletRequest) request; ++ HttpServletResponse res = (HttpServletResponse) response; ++ ++ if (!req.getMethod().equals("POST")) ++ { ++ res.setStatus(500, "Hessian Requires POST"); ++ PrintWriter out = res.getWriter(); ++ ++ res.setContentType("text/html"); ++ out.println("

Hessian Requires POST

"); ++ ++ return; ++ } ++ ++ String serviceInterface = req.getHeader("Interface-Name"); ++ ++ if (null == serviceInterface) ++ { ++ throw new ServletException( ++ "The service interface you reqeust is null. please check the client setting."); ++ } ++ ++ try ++ { ++ HessianSkeleton skeleton = findHessianSkeleton(serviceInterface); ++ ++ String serviceId = req.getPathInfo(); ++ ++ String objectId = req.getParameter("id"); ++ ++ if (objectId == null) ++ objectId = req.getParameter("ejbid"); ++ ++ ServiceContext.begin(req, serviceId, objectId); ++ ++ InputStream is = request.getInputStream(); ++ ++ OutputStream os = response.getOutputStream(); ++ ++ response.setContentType("application/x-hessian"); ++ ++ SerializerFactory serializerFactory = getSerializerFactory(); ++ ++ invoke(is, os, skeleton, serializerFactory); ++ } ++ catch (RuntimeException e) ++ { ++ throw e; ++ } ++ catch (ServletException e) ++ { ++ throw e; ++ } ++ catch (Throwable e) ++ { ++ throw new ServletException(e); ++ } ++ finally ++ { ++ ServiceContext.end(); ++ } ++ } ++ ++ ++ private HessianSkeleton findHessianSkeleton(String serviceInterface) ++ throws ServletException, ClassNotFoundException, ++ IllegalAccessException, InstantiationException ++ { ++ HessianSkeleton skeleton = null; ++ ++ if (registry.containsKey(serviceInterface))// find in cache first ++ { ++ skeleton = registry.get(serviceInterface); ++ } ++ else ++ // parse serviceImpl string to create skeleton. ++ { ++ String serviceImpl = (String) this.props.get(serviceInterface); ++ ++ if (null == serviceImpl) ++ { ++ throw new ServletException( ++ "Your request service of " ++ + serviceInterface ++ + " dose not exsit.please check the server configuration."); ++ } ++ if (serviceImpl.startsWith("#"))// for get bean from spring ++ { ++ skeleton = findSpringSkeleton(serviceInterface, serviceImpl); ++ } ++ else ++ { ++ skeleton = findLocalSkeleton(serviceInterface, serviceImpl); ++ } ++ ++ } ++ ++ registry.put(serviceInterface, skeleton); ++ ++ return skeleton; ++ } ++ ++ ++ private HessianSkeleton findLocalSkeleton(String serviceInterface, ++ String serviceImpl) throws ClassNotFoundException, ++ InstantiationException, IllegalAccessException, ServletException ++ { ++ HessianSkeleton skeleton; ++ Class homeClass = loadClass(serviceImpl); ++ ++ Object localBean = homeClass.newInstance(); ++ ++ init(localBean); ++ ++ skeleton = new HessianSkeleton(localBean, loadClass(serviceInterface)); ++ return skeleton; ++ } ++ ++ ++ private HessianSkeleton findSpringSkeleton(String serviceInterface, ++ String serviceImpl) throws ServletException, ClassNotFoundException ++ { ++ HessianSkeleton skeleton; ++ String beanId = serviceImpl.substring(1, serviceImpl.length()); ++ ++ ApplicationContext wac = WebApplicationContextUtils ++ .getWebApplicationContext(getServletContext()); ++ ++ Object springBean = wac.getBean(beanId.trim()); ++ ++ init(springBean); ++ ++ skeleton = new HessianSkeleton(springBean, loadClass(serviceInterface)); ++ ++ return skeleton; ++ } ++ ++ protected void invoke(InputStream is, OutputStream os, ++ HessianSkeleton skeleton, SerializerFactory serializerFactory) ++ throws Exception ++ { ++ skeleton.invoke(is, os, serializerFactory); ++ } ++ ++ protected Hessian2Input createHessian2Input(InputStream is) ++ { ++ return new Hessian2Input(is); ++ } ++ ++ static class LogWriter extends Writer ++ { ++ private Logger _log; ++ ++ private StringBuilder _sb = new StringBuilder(); ++ ++ LogWriter(Logger log) ++ { ++ _log = log; ++ } ++ ++ public void write(char ch) ++ { ++ if (ch == '\n' && _sb.length() > 0) ++ { ++ _log.fine(_sb.toString()); ++ _sb.setLength(0); ++ } ++ else ++ _sb.append((char) ch); ++ } ++ ++ public void write(char[] buffer, int offset, int length) ++ { ++ for (int i = 0; i < length; i++) ++ { ++ char ch = buffer[offset + i]; ++ ++ if (ch == '\n' && _sb.length() > 0) ++ { ++ _log.fine(_sb.toString()); ++ _sb.setLength(0); ++ } ++ else ++ _sb.append((char) ch); ++ } ++ } ++ ++ public void flush() ++ { ++ } ++ ++ public void close() ++ { ++ } ++ } ++} +diff -Npur hessian-4.0.65-src/com/caucho/hessian/server/HessianServlet.java hessian-4.0.65-fix/com/caucho/hessian/server/HessianServlet.java +--- hessian-4.0.65-src/com/caucho/hessian/server/HessianServlet.java 2020-07-23 12:51:28.000000000 +0800 ++++ hessian-4.0.65-fix/com/caucho/hessian/server/HessianServlet.java 2023-08-15 18:39:22.000000000 +0800 +@@ -1,477 +1,551 @@ +-/* +- * Copyright (c) 2001-2008 Caucho Technology, Inc. All rights reserved. +- * +- * The Apache Software License, Version 1.1 +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions +- * are met: +- * +- * 1. Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * +- * 2. Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in +- * the documentation and/or other materials provided with the +- * distribution. +- * +- * 3. The end-user documentation included with the redistribution, if +- * any, must include the following acknowlegement: +- * "This product includes software developed by the +- * Caucho Technology (http://www.caucho.com/)." +- * Alternately, this acknowlegement may appear in the software itself, +- * if and wherever such third-party acknowlegements normally appear. +- * +- * 4. The names "Hessian", "Resin", and "Caucho" must not be used to +- * endorse or promote products derived from this software without prior +- * written permission. For written permission, please contact +- * info@caucho.com. +- * +- * 5. Products derived from this software may not be called "Resin" +- * nor may "Resin" appear in their names without prior written +- * permission of Caucho Technology. +- * +- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +- * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS +- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +- * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- * +- * @author Scott Ferguson +- */ +- +-package com.caucho.hessian.server; +- +-import java.io.IOException; +-import java.io.InputStream; +-import java.io.OutputStream; +-import java.io.PrintWriter; +-import java.io.Writer; +-import java.util.logging.Logger; +- +-import javax.servlet.GenericServlet; +-import javax.servlet.Servlet; +-import javax.servlet.ServletConfig; +-import javax.servlet.ServletException; +-import javax.servlet.ServletRequest; +-import javax.servlet.ServletResponse; +-import javax.servlet.http.HttpServlet; +-import javax.servlet.http.HttpServletRequest; +-import javax.servlet.http.HttpServletResponse; +- +-import com.caucho.hessian.io.Hessian2Input; +-import com.caucho.hessian.io.SerializerFactory; +-import com.caucho.services.server.Service; +-import com.caucho.services.server.ServiceContext; +- +-/** +- * Servlet for serving Hessian services. +- * +- * Applications can use ServletContext inside a Hessian service to get +- * ServletRequest, ServletResponse and session information. +- */ +-@SuppressWarnings("serial") +-public class HessianServlet extends HttpServlet { +- private Class _homeAPI; +- private Object _homeImpl; +- +- private Class _objectAPI; +- private Object _objectImpl; +- +- private HessianSkeleton _homeSkeleton; +- private HessianSkeleton _objectSkeleton; +- +- private SerializerFactory _serializerFactory; +- +- public HessianServlet() +- { +- } +- +- public String getServletInfo() +- { +- return "Hessian Servlet"; +- } +- +- /** +- * Sets the home api. +- */ +- public void setHomeAPI(Class api) +- { +- _homeAPI = api; +- } +- +- /** +- * Sets the home implementation +- */ +- public void setHome(Object home) +- { +- _homeImpl = home; +- } +- +- /** +- * Sets the object api. +- */ +- public void setObjectAPI(Class api) +- { +- _objectAPI = api; +- } +- +- /** +- * Sets the object implementation +- */ +- public void setObject(Object object) +- { +- _objectImpl = object; +- } +- +- /** +- * Sets the service class. +- */ +- public void setService(Object service) +- { +- setHome(service); +- } +- +- /** +- * Sets the api-class. +- */ +- public void setAPIClass(Class api) +- { +- setHomeAPI(api); +- } +- +- /** +- * Gets the api-class. +- */ +- public Class getAPIClass() +- { +- return _homeAPI; +- } +- +- /** +- * Sets the serializer factory. +- */ +- public void setSerializerFactory(SerializerFactory factory) +- { +- _serializerFactory = factory; +- } +- +- /** +- * Gets the serializer factory. +- */ +- public SerializerFactory getSerializerFactory() +- { +- if (_serializerFactory == null) +- _serializerFactory = new SerializerFactory(); +- +- return _serializerFactory; +- } +- +- /** +- * Sets the serializer send collection java type. +- */ +- public void setSendCollectionType(boolean sendType) +- { +- getSerializerFactory().setSendCollectionType(sendType); +- } +- +- /** +- * Sets whitelist mode for the deserializer +- */ +- public void setWhitelist(boolean isWhitelist) +- { +- getSerializerFactory().getClassFactory().setWhitelist(isWhitelist); +- } +- +- /** +- * Adds an allow rule to the deserializer +- * +- * Examples: "java.util.*", "com.foo.io.Bean" +- */ +- public void allow(String pattern) +- { +- getSerializerFactory().getClassFactory().allow(pattern); +- } +- +- /** +- * Adds a deny rule to the deserializer +- */ +- public void deny(String pattern) +- { +- getSerializerFactory().getClassFactory().deny(pattern); +- } +- +- /** +- * Sets the debugging flag. +- */ +- public void setDebug(boolean isDebug) +- { +- } +- +- /** +- * Sets the debugging log name. +- */ +- public void setLogName(String name) +- { +- // _log = Logger.getLogger(name); +- } +- +- /** +- * Initialize the service, including the service object. +- */ +- public void init(ServletConfig config) +- throws ServletException +- { +- super.init(config); +- +- try { +- if (_homeImpl != null) { +- } +- else if (getInitParameter("home-class") != null) { +- String className = getInitParameter("home-class"); +- +- Class homeClass = loadClass(className); +- +- _homeImpl = homeClass.newInstance(); +- +- init(_homeImpl); +- } +- else if (getInitParameter("service-class") != null) { +- String className = getInitParameter("service-class"); +- +- Class homeClass = loadClass(className); +- +- _homeImpl = homeClass.newInstance(); +- +- init(_homeImpl); +- } +- else { +- if (getClass().equals(HessianServlet.class)) +- throw new ServletException("server must extend HessianServlet"); +- +- _homeImpl = this; +- } +- +- if (_homeAPI != null) { +- } +- else if (getInitParameter("home-api") != null) { +- String className = getInitParameter("home-api"); +- +- _homeAPI = loadClass(className); +- } +- else if (getInitParameter("api-class") != null) { +- String className = getInitParameter("api-class"); +- +- _homeAPI = loadClass(className); +- } +- else if (_homeImpl != null) { +- _homeAPI = findRemoteAPI(_homeImpl.getClass()); +- +- if (_homeAPI == null) +- _homeAPI = _homeImpl.getClass(); +- +- _homeAPI = _homeImpl.getClass(); +- } +- +- if (_objectImpl != null) { +- } +- else if (getInitParameter("object-class") != null) { +- String className = getInitParameter("object-class"); +- +- Class objectClass = loadClass(className); +- +- _objectImpl = objectClass.newInstance(); +- +- init(_objectImpl); +- } +- +- if (_objectAPI != null) { +- } +- else if (getInitParameter("object-api") != null) { +- String className = getInitParameter("object-api"); +- +- _objectAPI = loadClass(className); +- } +- else if (_objectImpl != null) +- _objectAPI = _objectImpl.getClass(); +- +- _homeSkeleton = new HessianSkeleton(_homeImpl, _homeAPI); +- +- if (_objectAPI != null) +- _homeSkeleton.setObjectClass(_objectAPI); +- +- if (_objectImpl != null) { +- _objectSkeleton = new HessianSkeleton(_objectImpl, _objectAPI); +- _objectSkeleton.setHomeClass(_homeAPI); +- } +- else +- _objectSkeleton = _homeSkeleton; +- +- if ("true".equals(getInitParameter("debug"))) { +- } +- +- if ("false".equals(getInitParameter("send-collection-type"))) +- setSendCollectionType(false); +- } catch (ServletException e) { +- throw e; +- } catch (Exception e) { +- throw new ServletException(e); +- } +- } +- +- private Class findRemoteAPI(Class implClass) +- { +- // hessian/34d0 +- return null; +- +- /* +- if (implClass == null || implClass.equals(GenericService.class)) +- return null; +- +- Class []interfaces = implClass.getInterfaces(); +- +- if (interfaces.length == 1) +- return interfaces[0]; +- +- return findRemoteAPI(implClass.getSuperclass()); +- */ +- } +- +- private Class loadClass(String className) +- throws ClassNotFoundException +- { +- ClassLoader loader = getContextClassLoader(); +- +- if (loader != null) +- return Class.forName(className, false, loader); +- else +- return Class.forName(className); +- } +- +- protected ClassLoader getContextClassLoader() +- { +- return Thread.currentThread().getContextClassLoader(); +- } +- +- private void init(Object service) +- throws ServletException +- { +- if (! this.getClass().equals(HessianServlet.class)) { +- } +- else if (service instanceof Service) +- ((Service) service).init(getServletConfig()); +- else if (service instanceof Servlet) +- ((Servlet) service).init(getServletConfig()); +- } +- +- /** +- * Execute a request. The path-info of the request selects the bean. +- * Once the bean's selected, it will be applied. +- */ +- public void service(ServletRequest request, ServletResponse response) +- throws IOException, ServletException +- { +- HttpServletRequest req = (HttpServletRequest) request; +- HttpServletResponse res = (HttpServletResponse) response; +- +- if (! req.getMethod().equals("POST")) { +- res.setStatus(500); // , "Hessian Requires POST"); +- PrintWriter out = res.getWriter(); +- +- res.setContentType("text/html"); +- out.println("

Hessian Requires POST

"); +- +- return; +- } +- +- String serviceId = req.getPathInfo(); +- String objectId = req.getParameter("id"); +- if (objectId == null) +- objectId = req.getParameter("ejbid"); +- +- ServiceContext.begin(req, res, serviceId, objectId); +- +- try { +- InputStream is = request.getInputStream(); +- OutputStream os = response.getOutputStream(); +- +- response.setContentType("x-application/hessian"); +- +- SerializerFactory serializerFactory = getSerializerFactory(); +- +- invoke(is, os, objectId, serializerFactory); +- } catch (RuntimeException e) { +- throw e; +- } catch (ServletException e) { +- throw e; +- } catch (Throwable e) { +- throw new ServletException(e); +- } finally { +- ServiceContext.end(); +- } +- } +- +- protected void invoke(InputStream is, OutputStream os, +- String objectId, +- SerializerFactory serializerFactory) +- throws Exception +- { +- if (objectId != null) +- _objectSkeleton.invoke(is, os, serializerFactory); +- else +- _homeSkeleton.invoke(is, os, serializerFactory); +- } +- +- protected Hessian2Input createHessian2Input(InputStream is) +- { +- return new Hessian2Input(is); +- } +- +- static class LogWriter extends Writer { +- private Logger _log; +- private StringBuilder _sb = new StringBuilder(); +- +- LogWriter(Logger log) +- { +- _log = log; +- } +- +- public void write(char ch) +- { +- if (ch == '\n' && _sb.length() > 0) { +- _log.fine(_sb.toString()); +- _sb.setLength(0); +- } +- else +- _sb.append((char) ch); +- } +- +- public void write(char []buffer, int offset, int length) +- { +- for (int i = 0; i < length; i++) { +- char ch = buffer[offset + i]; +- +- if (ch == '\n' && _sb.length() > 0) { +- _log.fine(_sb.toString()); +- _sb.setLength(0); +- } +- else +- _sb.append((char) ch); +- } +- } +- +- public void flush() +- { +- } +- +- public void close() +- { +- } +- } +-} ++/* ++ * Copyright (c) 2001-2008 Caucho Technology, Inc. All rights reserved. ++ * ++ * The Apache Software License, Version 1.1 ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * 3. The end-user documentation included with the redistribution, if ++ * any, must include the following acknowlegement: ++ * "This product includes software developed by the ++ * Caucho Technology (http://www.caucho.com/)." ++ * Alternately, this acknowlegement may appear in the software itself, ++ * if and wherever such third-party acknowlegements normally appear. ++ * ++ * 4. The names "Hessian", "Resin", and "Caucho" must not be used to ++ * endorse or promote products derived from this software without prior ++ * written permission. For written permission, please contact ++ * info@caucho.com. ++ * ++ * 5. Products derived from this software may not be called "Resin" ++ * nor may "Resin" appear in their names without prior written ++ * permission of Caucho Technology. ++ * ++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED ++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++ * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS ++ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, ++ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT ++ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ++ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE ++ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN ++ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * @author Scott Ferguson ++ */ ++ ++package com.caucho.hessian.server; ++ ++import java.io.IOException; ++import java.io.InputStream; ++import java.io.OutputStream; ++import java.io.PrintWriter; ++import java.io.Writer; ++import java.util.logging.Logger; ++ ++import javax.servlet.GenericServlet; ++import javax.servlet.Servlet; ++import javax.servlet.ServletConfig; ++import javax.servlet.ServletException; ++import javax.servlet.ServletRequest; ++import javax.servlet.ServletResponse; ++import javax.servlet.http.HttpServlet; ++import javax.servlet.http.HttpServletRequest; ++import javax.servlet.http.HttpServletResponse; ++ ++import org.springframework.context.ApplicationContext; ++import org.springframework.web.context.support.WebApplicationContextUtils; ++ ++import com.caucho.hessian.io.Hessian2Input; ++import com.caucho.hessian.io.SerializerFactory; ++import com.caucho.services.server.GenericService; ++import com.caucho.services.server.Service; ++import com.caucho.services.server.ServiceContext; ++ ++/** ++ * Servlet for serving Hessian services. ++ * ++ * Applications can use ServletContext inside a Hessian service to get ++ * ServletRequest, ServletResponse and session information. ++ */ ++@SuppressWarnings("serial") ++public class HessianServlet extends HttpServlet { ++ private static final long serialVersionUID = 1345616653808440850L; ++ private Logger _log = Logger.getLogger(HessianServlet.class.getName()); ++ private Class _homeAPI; ++ private Object _homeImpl; ++ ++ private Class _objectAPI; ++ private Object _objectImpl; ++ ++ private HessianSkeleton _homeSkeleton; ++ private HessianSkeleton _objectSkeleton; ++ ++ private SerializerFactory _serializerFactory; ++ private boolean _isDebug; ++ ++ public HessianServlet() ++ { ++ } ++ ++ public String getServletInfo() ++ { ++ return "Hessian Servlet"; ++ } ++ ++ /** ++ * Sets the home api. ++ */ ++ public void setHomeAPI(Class api) ++ { ++ _homeAPI = api; ++ } ++ ++ /** ++ * Sets the home implementation ++ */ ++ public void setHome(Object home) ++ { ++ _homeImpl = home; ++ } ++ ++ /** ++ * Sets the object api. ++ */ ++ public void setObjectAPI(Class api) ++ { ++ _objectAPI = api; ++ } ++ ++ /** ++ * Sets the object implementation ++ */ ++ public void setObject(Object object) ++ { ++ _objectImpl = object; ++ } ++ ++ /** ++ * Sets the service class. ++ */ ++ public void setService(Object service) ++ { ++ setHome(service); ++ } ++ ++ /** ++ * Sets the api-class. ++ */ ++ public void setAPIClass(Class api) ++ { ++ setHomeAPI(api); ++ } ++ ++ /** ++ * Gets the api-class. ++ */ ++ public Class getAPIClass() ++ { ++ return _homeAPI; ++ } ++ ++ /** ++ * Sets the serializer factory. ++ */ ++ public void setSerializerFactory(SerializerFactory factory) ++ { ++ _serializerFactory = factory; ++ } ++ ++ /** ++ * Gets the serializer factory. ++ */ ++ public SerializerFactory getSerializerFactory() ++ { ++ if (_serializerFactory == null) ++ _serializerFactory = new SerializerFactory(); ++ ++ return _serializerFactory; ++ } ++ ++ /** ++ * Sets the serializer send collection java type. ++ */ ++ public void setSendCollectionType(boolean sendType) ++ { ++ getSerializerFactory().setSendCollectionType(sendType); ++ } ++ ++ /** ++ * Sets whitelist mode for the deserializer ++ */ ++ public void setWhitelist(boolean isWhitelist) ++ { ++ getSerializerFactory().getClassFactory().setWhitelist(isWhitelist); ++ } ++ ++ /** ++ * Adds an allow rule to the deserializer ++ * ++ * Examples: "java.util.*", "com.foo.io.Bean" ++ */ ++ public void allow(String pattern) ++ { ++ getSerializerFactory().getClassFactory().allow(pattern); ++ } ++ ++ /** ++ * Adds a deny rule to the deserializer ++ */ ++ public void deny(String pattern) ++ { ++ getSerializerFactory().getClassFactory().deny(pattern); ++ } ++ ++ /** ++ * Sets the debugging flag. ++ */ ++ public void setDebug(boolean isDebug) ++ { ++ _isDebug = isDebug; ++ } ++ ++ /** ++ * Sets the debugging log name. ++ */ ++ public void setLogName(String name) ++ { ++ _log = Logger.getLogger(name); ++ } ++ ++ /** ++ * Initialize the service, including the service object. ++ */ ++ public void init(ServletConfig config) throws ServletException { ++ super.init(config); ++ ++ try { ++ String homeClassValue = getInitParameter("home-class"); ++ ++ if ((homeClassValue != null) & homeClassValue.startsWith("#")) //for get bean from spring ++ { ++ SpringPrepareForSkeleton(config, homeClassValue); ++ } else { ++ LocalPrepareForSkeleton(); ++ } ++ ++ _homeSkeleton = new HessianSkeleton(_homeImpl, _homeAPI); ++ ++ if (_objectAPI != null) { ++ _homeSkeleton.setObjectClass(_objectAPI); ++ } ++ ++ if (_objectImpl != null) { ++ _objectSkeleton = new HessianSkeleton(_objectImpl, _objectAPI); ++ _objectSkeleton.setHomeClass(_homeAPI); ++ } else { ++ _objectSkeleton = _homeSkeleton; ++ } ++ ++ if ("true".equals(getInitParameter("debug"))) { ++ _isDebug = true; ++ } ++ ++ if ("false".equals(getInitParameter("send-collection-type"))) { ++ setSendCollectionType(false); ++ } ++ } catch (ServletException e) { ++ throw e; ++ } catch (Exception e) { ++ throw new ServletException(e); ++ } ++ } ++ ++ /** ++ * TODO ++ * ++ * @param config ++ * @param homeClassValue ++ * @throws ServletException ++ */ ++ private void SpringPrepareForSkeleton(ServletConfig config, ++ String homeClassValue) ++ throws ClassNotFoundException, InstantiationException, ++ IllegalAccessException, ServletException { ++ if (getInitParameter("home-api") != null) { ++ String className = getInitParameter("home-api"); ++ _homeAPI = loadClass(className); ++ } ++ ++ String beanID = homeClassValue.substring(1, homeClassValue.length()); ++ ApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(config.getServletContext()); ++ _homeImpl = wac.getBean(beanID); ++ ++ init(_homeImpl); ++ } ++ ++ /** ++ * @throws ClassNotFoundException ++ * @throws InstantiationException ++ * @throws IllegalAccessException ++ * @throws ServletException ++ */ ++ private void LocalPrepareForSkeleton() ++ throws ClassNotFoundException, InstantiationException, ++ IllegalAccessException, ServletException { ++ ++ if (_homeImpl != null) { ++ } ++ else if (getInitParameter("home-class") != null) { ++ String className = getInitParameter("home-class"); ++ ++ Class homeClass = loadClass(className); ++ ++ _homeImpl = homeClass.newInstance(); ++ ++ init(_homeImpl); ++ } ++ else if (getInitParameter("service-class") != null) { ++ String className = getInitParameter("service-class"); ++ ++ Class homeClass = loadClass(className); ++ ++ _homeImpl = homeClass.newInstance(); ++ ++ init(_homeImpl); ++ } ++ else { ++ if (getClass().equals(HessianServlet.class)) ++ throw new ServletException("server must extend HessianServlet"); ++ ++ _homeImpl = this; ++ } ++ ++ if (_homeAPI != null) { ++ } ++ else if (getInitParameter("home-api") != null) { ++ String className = getInitParameter("home-api"); ++ ++ _homeAPI = loadClass(className); ++ } ++ else if (getInitParameter("api-class") != null) { ++ String className = getInitParameter("api-class"); ++ ++ _homeAPI = loadClass(className); ++ } ++ else if (_homeImpl != null) { ++ _homeAPI = findRemoteAPI(_homeImpl.getClass()); ++ ++ if (_homeAPI == null) ++ _homeAPI = _homeImpl.getClass(); ++ ++ // _homeAPI = _homeImpl.getClass(); ++ } ++ ++ if (_objectImpl != null) { ++ } ++ else if (getInitParameter("object-class") != null) { ++ String className = getInitParameter("object-class"); ++ ++ Class objectClass = loadClass(className); ++ ++ _objectImpl = objectClass.newInstance(); ++ ++ init(_objectImpl); ++ } ++ ++ if (_objectAPI != null) { ++ } ++ else if (getInitParameter("object-api") != null) { ++ String className = getInitParameter("object-api"); ++ ++ _objectAPI = loadClass(className); ++ } ++ else if (_objectImpl != null) ++ _objectAPI = _objectImpl.getClass(); ++ ++ /* _homeSkeleton = new HessianSkeleton(_homeImpl, _homeAPI); ++ ++ if (_objectAPI != null) ++ _homeSkeleton.setObjectClass(_objectAPI); ++ ++ if (_objectImpl != null) { ++ _objectSkeleton = new HessianSkeleton(_objectImpl, _objectAPI); ++ _objectSkeleton.setHomeClass(_homeAPI); ++ } ++ else ++ _objectSkeleton = _homeSkeleton; ++ ++ if ("true".equals(getInitParameter("debug"))) { ++ } ++ ++ if ("false".equals(getInitParameter("send-collection-type"))) ++ setSendCollectionType(false); ++ } catch (ServletException e) { ++ throw e; ++ } catch (Exception e) { ++ throw new ServletException(e); ++ } ++ */ ++ ++ } ++ ++ private Class findRemoteAPI(Class implClass) ++ { ++ ++ if (implClass == null || implClass.equals(GenericService.class)) ++ return null; ++ ++ Class []interfaces = implClass.getInterfaces(); ++ ++ if (interfaces.length == 1) ++ return interfaces[0]; ++ ++ return findRemoteAPI(implClass.getSuperclass()); ++ ++ } ++ ++ private Class loadClass(String className) ++ throws ClassNotFoundException ++ { ++ ClassLoader loader = getContextClassLoader(); ++ ++ if (loader != null) ++ return Class.forName(className, false, loader); ++ else ++ return Class.forName(className); ++ } ++ ++ protected ClassLoader getContextClassLoader() ++ { ++ return Thread.currentThread().getContextClassLoader(); ++ } ++ ++ private void init(Object service) ++ throws ServletException ++ { ++ if (! this.getClass().equals(HessianServlet.class)) { ++ } ++ else if (service instanceof Service) ++ ((Service) service).init(getServletConfig()); ++ else if (service instanceof Servlet) ++ ((Servlet) service).init(getServletConfig()); ++ } ++ ++ /** ++ * Execute a request. The path-info of the request selects the bean. ++ * Once the bean's selected, it will be applied. ++ */ ++ public void service(ServletRequest request, ServletResponse response) ++ throws IOException, ServletException ++ { ++ HttpServletRequest req = (HttpServletRequest) request; ++ HttpServletResponse res = (HttpServletResponse) response; ++ ++ if (! req.getMethod().equals("POST")) { ++ res.setStatus(500); // , "Hessian Requires POST"); ++ PrintWriter out = res.getWriter(); ++ ++ res.setContentType("text/html"); ++ out.println("

Hessian Requires POST

"); ++ ++ return; ++ } ++ ++ String serviceId = req.getPathInfo(); ++ String objectId = req.getParameter("id"); ++ if (objectId == null) ++ objectId = req.getParameter("ejbid"); ++ ++ ServiceContext.begin(req, res, serviceId, objectId); ++ ++ try { ++ InputStream is = request.getInputStream(); ++ OutputStream os = response.getOutputStream(); ++ ++ response.setContentType("x-application/hessian"); ++ ++ SerializerFactory serializerFactory = getSerializerFactory(); ++ ++ invoke(is, os, objectId, serializerFactory); ++ } catch (RuntimeException e) { ++ throw e; ++ } catch (ServletException e) { ++ throw e; ++ } catch (Throwable e) { ++ throw new ServletException(e); ++ } finally { ++ ServiceContext.end(); ++ } ++ } ++ ++ protected void invoke(InputStream is, OutputStream os, ++ String objectId, ++ SerializerFactory serializerFactory) ++ throws Exception ++ { ++ if (objectId != null) ++ _objectSkeleton.invoke(is, os, serializerFactory); ++ else ++ _homeSkeleton.invoke(is, os, serializerFactory); ++ } ++ ++ protected Hessian2Input createHessian2Input(InputStream is) ++ { ++ return new Hessian2Input(is); ++ } ++ ++ static class LogWriter extends Writer { ++ private Logger _log; ++ private StringBuilder _sb = new StringBuilder(); ++ ++ LogWriter(Logger log) ++ { ++ _log = log; ++ } ++ ++ public void write(char ch) ++ { ++ if (ch == '\n' && _sb.length() > 0) { ++ _log.fine(_sb.toString()); ++ _sb.setLength(0); ++ } ++ else ++ _sb.append((char) ch); ++ } ++ ++ public void write(char []buffer, int offset, int length) ++ { ++ for (int i = 0; i < length; i++) { ++ char ch = buffer[offset + i]; ++ ++ if (ch == '\n' && _sb.length() > 0) { ++ _log.fine(_sb.toString()); ++ _sb.setLength(0); ++ } ++ else ++ _sb.append((char) ch); ++ } ++ } ++ ++ public void flush() ++ { ++ } ++ ++ public void close() ++ { ++ } ++ } ++} +diff -Npur hessian-4.0.65-src/com/caucho/services/server/ServiceContext.java hessian-4.0.65-fix/com/caucho/services/server/ServiceContext.java +--- hessian-4.0.65-src/com/caucho/services/server/ServiceContext.java 2020-07-23 12:51:28.000000000 +0800 ++++ hessian-4.0.65-fix/com/caucho/services/server/ServiceContext.java 2023-08-15 18:39:24.000000000 +0800 +@@ -1,259 +1,274 @@ +-/* +- * Copyright (c) 2001-2008 Caucho Technology, Inc. All rights reserved. +- * +- * The Apache Software License, Version 1.1 +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions +- * are met: +- * +- * 1. Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * +- * 2. Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in +- * the documentation and/or other materials provided with the +- * distribution. +- * +- * 3. The end-user documentation included with the redistribution, if +- * any, must include the following acknowlegement: +- * "This product includes software developed by the +- * Caucho Technology (http://www.caucho.com/)." +- * Alternately, this acknowlegement may appear in the software itself, +- * if and wherever such third-party acknowlegements normally appear. +- * +- * 4. The names "Hessian", "Resin", and "Caucho" must not be used to +- * endorse or promote products derived from this software without prior +- * written permission. For written permission, please contact +- * info@caucho.com. +- * +- * 5. Products derived from this software may not be called "Resin" +- * nor may "Resin" appear in their names without prior written +- * permission of Caucho Technology. +- * +- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +- * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS +- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +- * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- * +- * @author Scott Ferguson +- */ +- +-package com.caucho.services.server; +- +-import javax.servlet.ServletException; +-import javax.servlet.ServletRequest; +-import javax.servlet.ServletResponse; +- +-import java.util.HashMap; +- +-/** +- * Context for a service, to handle request-specific information. +- * +- * Applications can use the ServiceContext to get servlet session ids or +- * HTTP headers. +- * +- *
+- * ServletRequest req = ServiceContext.getContext().getRequest();
+- * 
+- */ +-public class ServiceContext { +- private static final ThreadLocal _localContext +- = new ThreadLocal(); +- +- private ServletRequest _request; +- private ServletResponse _response; +- private String _serviceName; +- private String _objectId; +- private int _count; +- private HashMap _headers = new HashMap(); +- +- private ServiceContext() +- { +- } +- +- /** +- * Sets the request object prior to calling the service's method. +- * +- * @param request the calling servlet request +- * @param serviceId the service identifier +- * @param objectId the object identifier +- */ +- public static void begin(ServletRequest request, +- ServletResponse response, +- String serviceName, +- String objectId) +- throws ServletException +- { +- ServiceContext context = (ServiceContext) _localContext.get(); +- +- if (context == null) { +- context = new ServiceContext(); +- _localContext.set(context); +- } +- +- context._request = request; +- context._response = response; +- context._serviceName = serviceName; +- context._objectId = objectId; +- context._count++; +- } +- +- /** +- * Returns the service request. +- */ +- public static ServiceContext getContext() +- { +- return (ServiceContext) _localContext.get(); +- } +- +- /** +- * Adds a header. +- */ +- public void addHeader(String header, Object value) +- { +- _headers.put(header, value); +- } +- +- /** +- * Gets a header. +- */ +- public Object getHeader(String header) +- { +- return _headers.get(header); +- } +- +- /** +- * Gets a header from the context. +- */ +- public static Object getContextHeader(String header) +- { +- ServiceContext context = (ServiceContext) _localContext.get(); +- +- if (context != null) +- return context.getHeader(header); +- else +- return null; +- } +- +- /** +- * Returns the service request. +- */ +- public static ServletRequest getContextRequest() +- { +- ServiceContext context = (ServiceContext) _localContext.get(); +- +- if (context != null) +- return context._request; +- else +- return null; +- } +- +- /** +- * Returns the service request. +- */ +- public static ServletResponse getContextResponse() +- { +- ServiceContext context = (ServiceContext) _localContext.get(); +- +- if (context != null) +- return context._response; +- else +- return null; +- } +- +- /** +- * Returns the service id, corresponding to the pathInfo of the URL. +- */ +- public static String getContextServiceName() +- { +- ServiceContext context = (ServiceContext) _localContext.get(); +- +- if (context != null) +- return context._serviceName; +- else +- return null; +- } +- +- /** +- * Returns the object id, corresponding to the ?id= of the URL. +- */ +- public static String getContextObjectId() +- { +- ServiceContext context = (ServiceContext) _localContext.get(); +- +- if (context != null) +- return context._objectId; +- else +- return null; +- } +- +- /** +- * Cleanup at the end of a request. +- */ +- public static void end() +- { +- ServiceContext context = (ServiceContext) _localContext.get(); +- +- if (context != null && --context._count == 0) { +- context._request = null; +- context._response = null; +- +- context._headers.clear(); +- +- _localContext.set(null); +- } +- } +- +- /** +- * Returns the service request. +- * +- * @deprecated +- */ +- public static ServletRequest getRequest() +- { +- ServiceContext context = (ServiceContext) _localContext.get(); +- +- if (context != null) +- return context._request; +- else +- return null; +- } +- +- /** +- * Returns the service id, corresponding to the pathInfo of the URL. +- * +- * @deprecated +- */ +- public static String getServiceName() +- { +- ServiceContext context = (ServiceContext) _localContext.get(); +- +- if (context != null) +- return context._serviceName; +- else +- return null; +- } +- +- /** +- * Returns the object id, corresponding to the ?id= of the URL. +- * +- * @deprecated +- */ +- public static String getObjectId() +- { +- ServiceContext context = (ServiceContext) _localContext.get(); +- +- if (context != null) +- return context._objectId; +- else +- return null; +- } +-} ++/* ++ * Copyright (c) 2001-2008 Caucho Technology, Inc. All rights reserved. ++ * ++ * The Apache Software License, Version 1.1 ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * 3. The end-user documentation included with the redistribution, if ++ * any, must include the following acknowlegement: ++ * "This product includes software developed by the ++ * Caucho Technology (http://www.caucho.com/)." ++ * Alternately, this acknowlegement may appear in the software itself, ++ * if and wherever such third-party acknowlegements normally appear. ++ * ++ * 4. The names "Hessian", "Resin", and "Caucho" must not be used to ++ * endorse or promote products derived from this software without prior ++ * written permission. For written permission, please contact ++ * info@caucho.com. ++ * ++ * 5. Products derived from this software may not be called "Resin" ++ * nor may "Resin" appear in their names without prior written ++ * permission of Caucho Technology. ++ * ++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED ++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++ * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS ++ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, ++ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT ++ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ++ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ++ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE ++ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN ++ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * @author Scott Ferguson ++ */ ++ ++package com.caucho.services.server; ++ ++import javax.servlet.ServletException; ++import javax.servlet.ServletRequest; ++import javax.servlet.ServletResponse; ++ ++import java.util.HashMap; ++ ++/** ++ * Context for a service, to handle request-specific information. ++ * ++ * Applications can use the ServiceContext to get servlet session ids or ++ * HTTP headers. ++ * ++ *
++ * ServletRequest req = ServiceContext.getContext().getRequest();
++ * 
++ */ ++public class ServiceContext { ++ private static final ThreadLocal _localContext ++ = new ThreadLocal(); ++ ++ private ServletRequest _request; ++ private ServletResponse _response; ++ private String _serviceName; ++ private String _objectId; ++ private int _count; ++ private HashMap _headers = new HashMap(); ++ ++ private ServiceContext() ++ { ++ } ++ ++ /** ++ * Sets the request object prior to calling the service's method. ++ * ++ * @param request the calling servlet request ++ * @param serviceId the service identifier ++ * @param objectId the object identifier ++ */ ++ public static void begin(ServletRequest request, ++ ServletResponse response, ++ String serviceName, ++ String objectId) ++ throws ServletException ++ { ++ ServiceContext context = (ServiceContext) _localContext.get(); ++ ++ if (context == null) { ++ context = new ServiceContext(); ++ _localContext.set(context); ++ } ++ ++ context._request = request; ++ context._response = response; ++ context._serviceName = serviceName; ++ context._objectId = objectId; ++ context._count++; ++ } ++ ++ public static void begin(ServletRequest request, String serviceName, ++ String objectId) throws ServletException { ++ ServiceContext context = (ServiceContext) _localContext.get(); ++ ++ if (context == null) { ++ context = new ServiceContext(); ++ _localContext.set(context); ++ } ++ ++ context._request = request; ++ context._serviceName = serviceName; ++ context._objectId = objectId; ++ context._count++; ++ } ++ ++ /** ++ * Returns the service request. ++ */ ++ public static ServiceContext getContext() ++ { ++ return (ServiceContext) _localContext.get(); ++ } ++ ++ /** ++ * Adds a header. ++ */ ++ public void addHeader(String header, Object value) ++ { ++ _headers.put(header, value); ++ } ++ ++ /** ++ * Gets a header. ++ */ ++ public Object getHeader(String header) ++ { ++ return _headers.get(header); ++ } ++ ++ /** ++ * Gets a header from the context. ++ */ ++ public static Object getContextHeader(String header) ++ { ++ ServiceContext context = (ServiceContext) _localContext.get(); ++ ++ if (context != null) ++ return context.getHeader(header); ++ else ++ return null; ++ } ++ ++ /** ++ * Returns the service request. ++ */ ++ public static ServletRequest getContextRequest() ++ { ++ ServiceContext context = (ServiceContext) _localContext.get(); ++ ++ if (context != null) ++ return context._request; ++ else ++ return null; ++ } ++ ++ /** ++ * Returns the service request. ++ */ ++ public static ServletResponse getContextResponse() ++ { ++ ServiceContext context = (ServiceContext) _localContext.get(); ++ ++ if (context != null) ++ return context._response; ++ else ++ return null; ++ } ++ ++ /** ++ * Returns the service id, corresponding to the pathInfo of the URL. ++ */ ++ public static String getContextServiceName() ++ { ++ ServiceContext context = (ServiceContext) _localContext.get(); ++ ++ if (context != null) ++ return context._serviceName; ++ else ++ return null; ++ } ++ ++ /** ++ * Returns the object id, corresponding to the ?id= of the URL. ++ */ ++ public static String getContextObjectId() ++ { ++ ServiceContext context = (ServiceContext) _localContext.get(); ++ ++ if (context != null) ++ return context._objectId; ++ else ++ return null; ++ } ++ ++ /** ++ * Cleanup at the end of a request. ++ */ ++ public static void end() ++ { ++ ServiceContext context = (ServiceContext) _localContext.get(); ++ ++ if (context != null && --context._count == 0) { ++ context._request = null; ++ context._response = null; ++ ++ context._headers.clear(); ++ ++ _localContext.set(null); ++ } ++ } ++ ++ /** ++ * Returns the service request. ++ * ++ * @deprecated ++ */ ++ public static ServletRequest getRequest() ++ { ++ ServiceContext context = (ServiceContext) _localContext.get(); ++ ++ if (context != null) ++ return context._request; ++ else ++ return null; ++ } ++ ++ /** ++ * Returns the service id, corresponding to the pathInfo of the URL. ++ * ++ * @deprecated ++ */ ++ public static String getServiceName() ++ { ++ ServiceContext context = (ServiceContext) _localContext.get(); ++ ++ if (context != null) ++ return context._serviceName; ++ else ++ return null; ++ } ++ ++ /** ++ * Returns the object id, corresponding to the ?id= of the URL. ++ * ++ * @deprecated ++ */ ++ public static String getObjectId() ++ { ++ ServiceContext context = (ServiceContext) _localContext.get(); ++ ++ if (context != null) ++ return context._objectId; ++ else ++ return null; ++ } ++} diff --git a/hessian-4.0.65.pom b/hessian-4.0.65.pom index 7d7d745..27ddb9b 100644 --- a/hessian-4.0.65.pom +++ b/hessian-4.0.65.pom @@ -37,6 +37,11 @@ servlet-api 2.5 provided + + + org.springframework + spring-web + 3.2.18.RELEASE diff --git a/hessian.spec b/hessian.spec index 8f93372..ff5e8f6 100644 --- a/hessian.spec +++ b/hessian.spec @@ -1,15 +1,18 @@ Name: hessian Summary: Java implementation of a binary protocol for web services Version: 4.0.65 -Release: 1 +Release: 2 Epoch: 0 License: ASL 1.1 URL: http://hessian.caucho.com/ Source0: http://caucho.com/download/%{name}-%{version}-src.jar Source1: https://repo1.maven.org/maven2/com/caucho/%{name}/%{version}/%{name}-%{version}.pom Source2: https://opensource.org/licenses/Apache-1.1#/Apache-1.1.html#/Apache-1.1 -BuildRequires: maven-local mvn(javax.servlet:javax.servlet-api) -BuildRequires: mvn(org.apache.felix:maven-bundle-plugin) +BuildRequires: maven-local mvn(javax.servlet:javax.servlet-api) mvn(org.springframework:spring-web) +BuildRequires: mvn(org.apache.felix:maven-bundle-plugin) + +Patch1: %{name}-20230907.patch + BuildArch: noarch %description This is the Java implementation of Caucho's Hession binary transport @@ -21,7 +24,8 @@ Summary: API documentation for %{name} API documentation for %{name}. %prep -%setup -q -c +%autosetup -c -p1 + mkdir src mv com src/ rm -r META-INF @@ -29,6 +33,7 @@ rm -r src/com/caucho/hessian/test cp -p %{SOURCE1} pom.xml cp -p %{SOURCE2} apache.license.html %pom_change_dep :servlet-api javax.servlet:javax.servlet-api:3.1.0 +%pom_change_dep :spring-web org.springframework:spring-web:3.2.18.RELEASE %pom_remove_plugin :maven-gpg-plugin %pom_remove_plugin :maven-javadoc-plugin %pom_remove_plugin :maven-source-plugin @@ -69,6 +74,9 @@ cp -p %{SOURCE2} apache.license.html %license apache.license.html %changelog +* Tue Aug 29 2023 Bin Huang - 0:4.0.65-2 +- commit patch + * Mon Aug 21 2023 Bin Huang - 0:4.0.65-1 - Package update version to 4.0.65 -- Gitee