6986 lines
202 KiB
Diff
6986 lines
202 KiB
Diff
|
|
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<Method,String> _mangleMap
|
||
|
|
- = new WeakHashMap<Method,String>();
|
||
|
|
-
|
||
|
|
- 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<Method,String> _mangleMap
|
||
|
|
+ = new WeakHashMap<Method,String>();
|
||
|
|
+
|
||
|
|
+ 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<ClassLoader,SoftReference<ContextSerializerFactory>>
|
||
|
|
- _contextRefMap
|
||
|
|
- = new WeakHashMap<ClassLoader,SoftReference<ContextSerializerFactory>>();
|
||
|
|
-
|
||
|
|
- private static final ClassLoader _systemClassLoader;
|
||
|
|
-
|
||
|
|
- private static HashMap<String,Serializer> _staticSerializerMap;
|
||
|
|
- private static HashMap<String,Deserializer> _staticDeserializerMap;
|
||
|
|
- private static HashMap _staticClassNameMap;
|
||
|
|
-
|
||
|
|
- private ContextSerializerFactory _parent;
|
||
|
|
- private WeakReference<ClassLoader> _loaderRef;
|
||
|
|
-
|
||
|
|
- private final HashSet<String> _serializerFiles = new HashSet<String>();
|
||
|
|
- private final HashSet<String> _deserializerFiles = new HashSet<String>();
|
||
|
|
-
|
||
|
|
- private final HashMap<String,Serializer> _serializerClassMap
|
||
|
|
- = new HashMap<String,Serializer>();
|
||
|
|
-
|
||
|
|
- private final ConcurrentHashMap<String,Serializer> _customSerializerMap
|
||
|
|
- = new ConcurrentHashMap<String,Serializer>();
|
||
|
|
-
|
||
|
|
- private final HashMap<Class<?>,Serializer> _serializerInterfaceMap
|
||
|
|
- = new HashMap<Class<?>,Serializer>();
|
||
|
|
-
|
||
|
|
- private final HashMap<String,Deserializer> _deserializerClassMap
|
||
|
|
- = new HashMap<String,Deserializer>();
|
||
|
|
-
|
||
|
|
- private final HashMap<String,Deserializer> _deserializerClassNameMap
|
||
|
|
- = new HashMap<String,Deserializer>();
|
||
|
|
-
|
||
|
|
- private final ConcurrentHashMap<String,Deserializer> _customDeserializerMap
|
||
|
|
- = new ConcurrentHashMap<String,Deserializer>();
|
||
|
|
-
|
||
|
|
- private final HashMap<Class<?>,Deserializer> _deserializerInterfaceMap
|
||
|
|
- = new HashMap<Class<?>,Deserializer>();
|
||
|
|
-
|
||
|
|
- public ContextSerializerFactory(ContextSerializerFactory parent,
|
||
|
|
- ClassLoader loader)
|
||
|
|
- {
|
||
|
|
- if (loader == null)
|
||
|
|
- loader = _systemClassLoader;
|
||
|
|
-
|
||
|
|
- _loaderRef = new WeakReference<ClassLoader>(loader);
|
||
|
|
-
|
||
|
|
- init();
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- public static ContextSerializerFactory create()
|
||
|
|
- {
|
||
|
|
- return create(Thread.currentThread().getContextClassLoader());
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- public static ContextSerializerFactory create(ClassLoader loader)
|
||
|
|
- {
|
||
|
|
- synchronized (_contextRefMap) {
|
||
|
|
- SoftReference<ContextSerializerFactory> 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<ContextSerializerFactory>(factory);
|
||
|
|
-
|
||
|
|
- _contextRefMap.put(loader, factoryRef);
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- return factory;
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- public ClassLoader getClassLoader()
|
||
|
|
- {
|
||
|
|
- WeakReference<ClassLoader> 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<Class,Class> classMap;
|
||
|
|
-
|
||
|
|
- classMap = new HashMap<Class,Class>();
|
||
|
|
- initSerializerFiles("META-INF/hessian/serializers",
|
||
|
|
- _serializerFiles,
|
||
|
|
- classMap,
|
||
|
|
- Serializer.class);
|
||
|
|
-
|
||
|
|
- for (Map.Entry<Class,Class> 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<Class,Class>();
|
||
|
|
- initSerializerFiles("META-INF/hessian/deserializers",
|
||
|
|
- _deserializerFiles,
|
||
|
|
- classMap,
|
||
|
|
- Deserializer.class);
|
||
|
|
-
|
||
|
|
- for (Map.Entry<Class,Class> 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<String> fileList,
|
||
|
|
- HashMap<Class,Class> 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<ClassLoader,SoftReference<ContextSerializerFactory>>
|
||
|
|
+ _contextRefMap
|
||
|
|
+ = new WeakHashMap<ClassLoader,SoftReference<ContextSerializerFactory>>();
|
||
|
|
+
|
||
|
|
+ private static final ClassLoader _systemClassLoader;
|
||
|
|
+
|
||
|
|
+ private static HashMap<String,Serializer> _staticSerializerMap;
|
||
|
|
+ private static HashMap<String,Deserializer> _staticDeserializerMap;
|
||
|
|
+ private static HashMap _staticClassNameMap;
|
||
|
|
+
|
||
|
|
+ private ContextSerializerFactory _parent;
|
||
|
|
+ private WeakReference<ClassLoader> _loaderRef;
|
||
|
|
+
|
||
|
|
+ private final HashSet<String> _serializerFiles = new HashSet<String>();
|
||
|
|
+ private final HashSet<String> _deserializerFiles = new HashSet<String>();
|
||
|
|
+
|
||
|
|
+ private final HashMap<String,Serializer> _serializerClassMap
|
||
|
|
+ = new HashMap<String,Serializer>();
|
||
|
|
+
|
||
|
|
+ private final ConcurrentHashMap<String,Serializer> _customSerializerMap
|
||
|
|
+ = new ConcurrentHashMap<String,Serializer>();
|
||
|
|
+
|
||
|
|
+ private final HashMap<Class<?>,Serializer> _serializerInterfaceMap
|
||
|
|
+ = new HashMap<Class<?>,Serializer>();
|
||
|
|
+
|
||
|
|
+ private final HashMap<String,Deserializer> _deserializerClassMap
|
||
|
|
+ = new HashMap<String,Deserializer>();
|
||
|
|
+
|
||
|
|
+ private final HashMap<String,Deserializer> _deserializerClassNameMap
|
||
|
|
+ = new HashMap<String,Deserializer>();
|
||
|
|
+
|
||
|
|
+ private final ConcurrentHashMap<String,Deserializer> _customDeserializerMap
|
||
|
|
+ = new ConcurrentHashMap<String,Deserializer>();
|
||
|
|
+
|
||
|
|
+ private final HashMap<Class<?>,Deserializer> _deserializerInterfaceMap
|
||
|
|
+ = new HashMap<Class<?>,Deserializer>();
|
||
|
|
+
|
||
|
|
+ public ContextSerializerFactory(ContextSerializerFactory parent,
|
||
|
|
+ ClassLoader loader)
|
||
|
|
+ {
|
||
|
|
+ if (loader == null)
|
||
|
|
+ loader = _systemClassLoader;
|
||
|
|
+
|
||
|
|
+ _loaderRef = new WeakReference<ClassLoader>(loader);
|
||
|
|
+
|
||
|
|
+ init();
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ public static ContextSerializerFactory create()
|
||
|
|
+ {
|
||
|
|
+ return create(Thread.currentThread().getContextClassLoader());
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ public static ContextSerializerFactory create(ClassLoader loader)
|
||
|
|
+ {
|
||
|
|
+ synchronized (_contextRefMap) {
|
||
|
|
+ SoftReference<ContextSerializerFactory> 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<ContextSerializerFactory>(factory);
|
||
|
|
+
|
||
|
|
+ _contextRefMap.put(loader, factoryRef);
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ return factory;
|
||
|
|
+ }
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ public ClassLoader getClassLoader()
|
||
|
|
+ {
|
||
|
|
+ WeakReference<ClassLoader> 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<Class,Class> classMap;
|
||
|
|
+
|
||
|
|
+ classMap = new HashMap<Class,Class>();
|
||
|
|
+ initSerializerFiles("META-INF/hessian/serializers",
|
||
|
|
+ _serializerFiles,
|
||
|
|
+ classMap,
|
||
|
|
+ Serializer.class);
|
||
|
|
+
|
||
|
|
+ for (Map.Entry<Class,Class> 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<Class,Class>();
|
||
|
|
+ initSerializerFiles("META-INF/hessian/deserializers",
|
||
|
|
+ _deserializerFiles,
|
||
|
|
+ classMap,
|
||
|
|
+ Deserializer.class);
|
||
|
|
+
|
||
|
|
+ for (Map.Entry<Class,Class> 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<String> fileList,
|
||
|
|
+ HashMap<Class,Class> 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<String,FieldDeserializer> _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<String,FieldDeserializer> getFieldMap(Class<?> cl)
|
||
|
|
+ {
|
||
|
|
+ HashMap<String,FieldDeserializer> fieldMap
|
||
|
|
+ = new HashMap<String,FieldDeserializer>();
|
||
|
|
+
|
||
|
|
+ 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<Class<?>,SoftReference<NonTransientUnsafeSerializer>> _serializerMap
|
||
|
|
+ = new WeakHashMap<Class<?>,SoftReference<NonTransientUnsafeSerializer>>();
|
||
|
|
+
|
||
|
|
+ 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<NonTransientUnsafeSerializer> baseRef
|
||
|
|
+ = _serializerMap.get(cl);
|
||
|
|
+
|
||
|
|
+ NonTransientUnsafeSerializer base = baseRef != null ? baseRef.get() : null;
|
||
|
|
+
|
||
|
|
+ if (base == null) {
|
||
|
|
+ base = new NonTransientUnsafeSerializer(cl);
|
||
|
|
+ baseRef = new SoftReference<NonTransientUnsafeSerializer>(base);
|
||
|
|
+ _serializerMap.put(cl, baseRef);
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ return base;
|
||
|
|
+ }
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ protected void introspect(Class<?> cl)
|
||
|
|
+ {
|
||
|
|
+ ArrayList<Field> primitiveFields = new ArrayList<Field>();
|
||
|
|
+ ArrayList<Field> compoundFields = new ArrayList<Field>();
|
||
|
|
+
|
||
|
|
+ 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<Field> fields = new ArrayList<Field>();
|
||
|
|
+ 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<ClassLoader,SoftReference<SerializerFactory>>
|
||
|
|
- _defaultFactoryRefMap
|
||
|
|
- = new WeakHashMap<ClassLoader,SoftReference<SerializerFactory>>();
|
||
|
|
-
|
||
|
|
- private ContextSerializerFactory _contextFactory;
|
||
|
|
- private WeakReference<ClassLoader> _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<ClassLoader>(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<SerializerFactory> factoryRef
|
||
|
|
- = _defaultFactoryRefMap.get(loader);
|
||
|
|
-
|
||
|
|
- SerializerFactory factory = null;
|
||
|
|
-
|
||
|
|
- if (factoryRef != null)
|
||
|
|
- factory = factoryRef.get();
|
||
|
|
-
|
||
|
|
- if (factory == null) {
|
||
|
|
- factory = new SerializerFactory();
|
||
|
|
-
|
||
|
|
- factoryRef = new SoftReference<SerializerFactory>(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<ClassLoader,SoftReference<SerializerFactory>>
|
||
|
|
+ _defaultFactoryRefMap
|
||
|
|
+ = new WeakHashMap<ClassLoader,SoftReference<SerializerFactory>>();
|
||
|
|
+
|
||
|
|
+ private ContextSerializerFactory _contextFactory;
|
||
|
|
+ private WeakReference<ClassLoader> _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<ClassLoader>(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<SerializerFactory> factoryRef
|
||
|
|
+ = _defaultFactoryRefMap.get(loader);
|
||
|
|
+
|
||
|
|
+ SerializerFactory factory = null;
|
||
|
|
+
|
||
|
|
+ if (factoryRef != null)
|
||
|
|
+ factory = factoryRef.get();
|
||
|
|
+
|
||
|
|
+ if (factory == null) {
|
||
|
|
+ factory = new SerializerFactory();
|
||
|
|
+
|
||
|
|
+ factoryRef = new SoftReference<SerializerFactory>(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<String, HessianSkeleton> registry = new ConcurrentHashMap<String, HessianSkeleton>();
|
||
|
|
+
|
||
|
|
+ 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("<h1>Hessian Requires POST</h1>");
|
||
|
|
+
|
||
|
|
+ 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("<h1>Hessian Requires POST</h1>");
|
||
|
|
-
|
||
|
|
- 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("<h1>Hessian Requires POST</h1>");
|
||
|
|
+
|
||
|
|
+ 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.
|
||
|
|
- *
|
||
|
|
- * <code><pre>
|
||
|
|
- * ServletRequest req = ServiceContext.getContext().getRequest();
|
||
|
|
- * </pre></code>
|
||
|
|
- */
|
||
|
|
-public class ServiceContext {
|
||
|
|
- private static final ThreadLocal<ServiceContext> _localContext
|
||
|
|
- = new ThreadLocal<ServiceContext>();
|
||
|
|
-
|
||
|
|
- 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.
|
||
|
|
+ *
|
||
|
|
+ * <code><pre>
|
||
|
|
+ * ServletRequest req = ServiceContext.getContext().getRequest();
|
||
|
|
+ * </pre></code>
|
||
|
|
+ */
|
||
|
|
+public class ServiceContext {
|
||
|
|
+ private static final ThreadLocal<ServiceContext> _localContext
|
||
|
|
+ = new ThreadLocal<ServiceContext>();
|
||
|
|
+
|
||
|
|
+ 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;
|
||
|
|
+ }
|
||
|
|
+}
|