转自网址:

http://bbs.51cto.com/thread-489819-1-1.html

  首先需要声明的是,本人出于技术爱好的角度,以下的文字只是对所看到的一些情况的罗列,偶尔附加个人的一些感慨,不代表其它任何组织或公司的色彩。本人也并不希望这篇贴子成为某些别有用心的人用来攻击某些厂商的武器。

作为一名有多年开发经验的J2EE技术人员,本人向来对J2EE应用服务器的相关知识比较感兴趣;或许又夹杂着一些民族感情,对号称国产中间件第一品牌东方通的应用服务器产品“TongWeb”倾慕不已。遗憾的是,东方通的网站上从来不放任何产品的下载,因此,对 TongWeb 到底是如何的庐山真面目,也无从得知。
    一个很偶然的机会,由于客户指定品牌的原因,获得了一份 TongWeb 的产品包,颇有些喜出望外,极欲一探究竟。在使用TongWeb的过程中,一个很偶然的因素,本人打开了TongWeb4.6\conf\ejb\trace.properties文件,发现了这样一行:
    log.config.classname org.objectweb.util.monolog.wrapper.log4j.MonologLoggerFactory
    不由心中一动,objectweb,好熟悉的名字,国外的开源服务器 JOnAS 不就出自这个组织吗?
    抱着疑惑的态度和本着技术人员寻根问底的精神,就开始了 TongWeb 与 JOnAS 的对比之旅。

进行Java程序的对比,自然是要对最主要的jar包进行对比了。
    根据“最大的就是最主要的”原则:TongWeb中最大的jar包是:TongWeb4.6\lib\tongweb.jar;JOnAS最大的jar包是:JOnAS-4.8.3\lib\commons\jonas\ow_jonas.jar
随便翻了关于 ejb 的一个包,以下是包名截图:

TongWEB与JOnAS 对比,国产中间件战斗机东方通TongWEB源码解析-LMLPHP

看起来很像?但不能够以最坏的恶意来揣测人家,不妨用反编译工具看一下具体的内容再说。
顺手选一个,就拿图片中显示的第一个类 BeanFactory 来说吧,以下是用Jad反编译出来的内容对比:

/***************org.objectweb.jonas_ejb.container.BeanFactory***************/
package org.objectweb.jonas_ejb.container; import java.util.Hashtable;
import javax.naming.InitialContext;
import javax.transaction.Transaction;
import org.objectweb.jonas_ejb.deployment.api.BeanDesc;
import org.objectweb.transaction.jta.TransactionManager; public interface BeanFactory { public abstract String getEJBName(); public abstract BeanDesc getDeploymentDescriptor(); public abstract int getPoolSize(); public abstract void stop(); public abstract void syncDirty(boolean flag); public abstract void reduceCache(); public abstract JHome getHome(); public abstract JLocalHome getLocalHome(); public abstract TransactionManager getTransactionManager(); public abstract JContainer getContainer(); public abstract Hashtable getEnv(); public abstract InitialContext getInitialContext(); public abstract void initInstancePool(); public abstract void restartTimers(); public abstract void storeInstances(Transaction transaction);
} /***********com.tongweb.teas_ejb.container.BeanFactory******************************/ package com.tongweb.teas_ejb.container; import com.tongweb.teas_ejb.deployment.api.BeanDesc;
import java.util.Hashtable;
import javax.naming.InitialContext;
import javax.transaction.TransactionManager; public interface BeanFactory { public abstract String getEJBName(); public abstract BeanDesc getDeploymentDescriptor(); public abstract int getPoolSize(); public abstract void stop(); public abstract void sync(); public abstract void reduceCache(); public abstract JHome getHome(); public abstract JLocalHome getLocalHome(); public abstract TransactionManager getTransactionManager(); public abstract JContainer getContainer(); public abstract Hashtable getEnv(); public abstract InitialContext getInitialContext();
}

  

这两个类很相像?在本人看来,何止是相像,简直就是一个模子刻出来的!只能说的是,版本不同而已!
还是不能以最坏的恶意来揣测TongWeb,不妨再换个包来看看。东方通不是号称消息中间件最强吗?不妨看看jms这个包。
不看不知道,一看吓一跳:

TongWEB与JOnAS 对比,国产中间件战斗机东方通TongWEB源码解析-LMLPHP

这个包下的所有类名称,竟然都是一模一样的,只不过一个位于org.objectweb.jonas_jms包下,一个位于com.tongweb.teas_jms 包下而已。
随便找个类JConnection来看看:

/**********************************org.objectweb.jonas_jms.JConnection***********/
package org.objectweb.jonas_jms; import java.util.LinkedList;
import javax.jms.*;
import org.objectweb.transaction.jta.TransactionManager;
import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger; public class JConnection
implements Connection
{ protected XAConnection xac;
protected boolean closed;
protected String user;
protected boolean globaltx;
protected static TransactionManager tm;
protected JConnectionFactory jcf;
protected LinkedList sessionlist;
protected static final String INTERNAL_USER_NAME =
"anInternalNameUsedOnlyByJOnAS"; protected JConnection(JConnectionFactory jcf, String user)
throws JMSException
{
globaltx = false;
sessionlist = new LinkedList();s
this.user = user;
this.jcf = jcf;
closed = false;
if(tm == null)
tm = JmsManagerImpl.getTransactionManager();
try
{
globaltx = tm.getTransaction() != null;
}
catch(Exception e) { }
} public JConnection(JConnectionFactory jcf, XAConnectionFactory xacf, String user, String passwd)
throws JMSException
{
this(jcf, user);
xac = xacf.createXAConnection(user, passwd);
} public JConnection(JConnectionFactory jcf, XAConnectionFactory xacf)
throws JMSException
{
this(jcf, "anInternalNameUsedOnlyByJOnAS");
xac = xacf.createXAConnection();
} protected synchronized boolean sessionOpen(Session s)
{
if(!closed)
{
sessionlist.add(s);
return true;
} else
{
return false;
}
} protected synchronized void sessionClose(Session s)
{
sessionlist.remove(s);
if(sessionlist.size() == 0 && closed)
notify();
} public String getUser()
{
return user;
} public void close()
throws JMSException
{
TraceJms.logger.log(BasicLevel.DEBUG, "");
if(globaltx)
{
jcf.freeJConnection(this);
} else
{
synchronized(this)
{
while(sessionlist.size() > 0)
try
{
wait();
}
catch(InterruptedException e)
{
TraceJms.logger.log(BasicLevel.ERROR, "interrupted");
}
}
closed = true;
xac.close();
}
} public void finalClose()
throws JMSException
{
if(!closed)
xac.close();
} public ConnectionConsumer createConnectionConsumer(Destination destination, String messageSelector, ServerSessionPool sessionPool, int maxMessages)
throws JMSException
{
TraceJms.logger.log(BasicLevel.DEBUG, "");
return xac.createConnectionConsumer(destination, messageSelector, sessionPool, maxMessages);
} public ConnectionConsumer createDurableConnectionConsumer(Topic topic, String subscriptionName, String messageSelector, ServerSessionPool sessionPool, int maxMessages)
throws JMSException
{
TraceJms.logger.log(BasicLevel.DEBUG, "");
return xac.createDurableConnectionConsumer(topic, subscriptionName, messageSelector, sessionPool, maxMessages);
} public Session createSession(boolean transacted, int acknowledgeMode)
throws JMSException
{
TraceJms.logger.log(BasicLevel.DEBUG, "");
return new JSession(this, xac);
} public String getClientID()
throws JMSException
{
TraceJms.logger.log(BasicLevel.DEBUG, "");
return xac.getClientID();
} public void setClientID(String clientID)
throws JMSException
{
TraceJms.logger.log(BasicLevel.DEBUG, "");
xac.setClientID(clientID);
} public ConnectionMetaData getMetaData()
throws JMSException
{
TraceJms.logger.log(BasicLevel.DEBUG, "");
return xac.getMetaData();
} public ExceptionListener getExceptionListener()
throws JMSException
{
TraceJms.logger.log(BasicLevel.DEBUG, "");
return xac.getExceptionListener();
} public void setExceptionListener(ExceptionListener listener)
throws JMSException
{
TraceJms.logger.log(BasicLevel.DEBUG, "");
xac.setExceptionListener(listener);
} public void start()
throws JMSException
{
TraceJms.logger.log(BasicLevel.DEBUG, "");
xac.start();
} public void stop()
throws JMSException
{
TraceJms.logger.log(BasicLevel.DEBUG, "");
xac.stop();
}
}
/***********************com.tongweb.teas_jms.JConnection**************************/
package com.tongweb.teas_jms; import java.util.LinkedList;
import javax.jms.*;
import javax.transaction.TransactionManager;
import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger; public class JConnection
implements Connection
{ protected XAConnection xac;
protected boolean closed;
protected String user;
protected boolean globaltx;
protected static TransactionManager tm;
protected JConnectionFactory jcf;
protected LinkedList sessionlist;
protected static final String INTERNAL_USER_NAME =
"anInternalNameUsedOnlyByJOnAS"; protected JConnection(JConnectionFactory jconnectionfactory, String s)
throws JMSException
{
globaltx = false;
sessionlist = new LinkedList();
user = s;
jcf = jconnectionfactory;
closed = false;
if(tm == null)
tm = JmsManagerImpl.getTransactionManager();
try
{
globaltx = tm.getTransaction() != null;
}
catch(Exception exception) { }
} public JConnection(JConnectionFactory jconnectionfactory, XAConnectionFactory xaconnectionfactory, String s, String s1)
throws JMSException
{
this(jconnectionfactory, s);
} public JConnection(JConnectionFactory jconnectionfactory, XAConnectionFactory xaconnectionfactory)
throws JMSException
{
this(jconnectionfactory, "anInternalNameUsedOnlyByJOnAS");
} protected synchronized boolean sessionOpen(Session session)
{
if(!closed)
{
sessionlist.add(session);
return true;
} else
{
return false;
}
} protected synchronized void sessionClose(Session session)
{
sessionlist.remove(session);
if(sessionlist.size() == 0 && closed)
notify();
} public String getUser()
{
return user;
} public void close()
throws JMSException
{
TraceJms.logger.log(BasicLevel.DEBUG, "");
if(globaltx)
{
jcf.freeJConnection(this);
} else
{
synchronized(this)
{
while(sessionlist.size() > 0)
try
{
wait();
}
catch(InterruptedException interruptedexception)
{
TraceJms.logger.log(BasicLevel.ERROR, "interrupted");
}
}
closed = true;
}
} public void finalClose()
throws JMSException
{
if(closed);
} public ConnectionConsumer createConnectionConsumer(Destination destination, String s, ServerSessionPool serversessionpool, int i)
throws JMSException
{
TraceJms.logger.log(BasicLevel.DEBUG, "");
return null;
} public ConnectionConsumer createDurableConnectionConsumer(Topic topic, String s, String s1, ServerSessionPool serversessionpool, int i)
throws JMSException
{
TraceJms.logger.log(BasicLevel.DEBUG, "");
return null;
} public Session createSession(boolean flag, int i)
throws JMSException
{
TraceJms.logger.log(BasicLevel.DEBUG, "");
return new JSession(this, xac);
} public String getClientID()
throws JMSException
{
TraceJms.logger.log(BasicLevel.DEBUG, "");
return null;
} public void setClientID(String s)
throws JMSException
{
TraceJms.logger.log(BasicLevel.DEBUG, "");
} public ConnectionMetaData getMetaData()
throws JMSException
{
TraceJms.logger.log(BasicLevel.DEBUG, "");
return null;
} public ExceptionListener getExceptionListener()
throws JMSException
{
TraceJms.logger.log(BasicLevel.DEBUG, "");
return null;
} public void setExceptionListener(ExceptionListener exceptionlistener)
throws JMSException
{
TraceJms.logger.log(BasicLevel.DEBUG, "");
} public void start()
throws JMSException
{
TraceJms.logger.log(BasicLevel.DEBUG, "");
} public void stop()
throws JMSException
{
TraceJms.logger.log(BasicLevel.DEBUG, "");
}
}

  两个类除了包名不同,其它基本上完全一致!甚至于TongWeb中竟然还存在这样一个常量声明:protected static final String INTERNAL_USER_NAME   = "anInternalNameUsedOnlyByJOnAS";
东方通啊东方通,拜托你抄袭也要有点专业精神好不好,不要用“俯卧撑”来敷衍我们!

最后,很想说点啥,但心里又堵得慌,不知道该说啥。这就是号称“国内第一品牌”的东方通的产品?我们已经见识过了汉芯,见识过了麒麟,难道还要再见识一下TongWeb?

TongWEB与JOnAS 对比,国产中间件战斗机东方通TongWEB源码解析

04-27 01:39