轉自網址:
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 的一個包,以下是包名截圖:
看起來很像?但不能夠以最壞的惡意來揣測人家,不妨用反編譯工具看一下具體的內容再說。
順手選一個,就拿圖片中顯示的第一個類 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這個包。
不看不知道,一看嚇一跳:
這個包下的所有類名稱,竟然都是一模一樣的,只不過一個位於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源碼解析