2008-09-19 130 views
10

當我用C/C++編寫庫時,我養成了一種返回編譯日期/時間的方法。這總是被編譯到庫中,所以會區分庫的構建。有沒有什麼辦法在編譯時爲Java定義一個常量值

C++:我在代碼中返回的#define得到這個

#ifdef _BuildDateTime_ 
    char* SomeClass::getBuildDateTime() { 
     return _BuildDateTime_; 
    } 
#else 
    char* SomeClass::getBuildDateTime() { 
     return "Undefined"; 
    } 
#endif 

然後在編譯我的構建腳本有一個「-D_BuildDateTime_ = Date」。

有沒有什麼辦法可以在Java中實現這個或類似的功能,而無需記住手動編輯任何文件或分發任何單獨的文件。

我從同事那裏得到的一個建議是讓ant文件在類路徑上創建一個文件,並將其打包到JAR中並通過該方法讀取它。

喜歡的東西(假設創建被稱爲「DateTime.dat」的文件):這是一個黑客,通過具有類似名稱的文件外面有人的可以繞過/破

// I know Exceptions and proper open/closing 
// of the file are not done. This is just 
// to explain the point! 
String getBuildDateTime() { 
    return new BufferedReader(getClass() 
      .getResourceAsStream("DateTime.dat")).readLine(); 
} 

在我看來, JAR,但在類路徑上。

不管怎樣,我的問題是,是否有什麼辦法在編譯時注入一個恆定的成類

編輯

我之所以考慮使用外部生成文件中的JAR一個黑客就是因爲這個)一個庫,並將嵌入到客戶端應用程序中。這些客戶端應用程序可能會定義他們自己的類加載器,這意味着我不能依賴於標準的JVM類加載規則。

我的個人偏好是使用serg10建議的JAR文件中的日期。

+0

*在我看來,這是一種破解,可以通過在JAR之外具有類似命名文件但在類路徑中的人來規避/破壞* 您在什麼工作環境中編程,擔心人們會「繞過「 這個? 讓Ant生成文件根本不是黑客。當然,清單方法甚至更好的是Java-ism(你也可以讓Ant自動化)。 – Hejazzman 2009-04-29 23:40:34

回答

15

我喜歡基於標準的方法。在罐子的Manifest File中放入您的版本信息(以及其他有用的發佈者資料,例如內部版本號,Subversion版本號,作者,公司詳細信息等)。

這是一個有文檔記錄和理解的Java規範。存在強大的工具支持來創建清單文件(例如core Ant taskmaven jar plugin)。這些可以幫助自動設置一些屬性 - 我有Maven配置爲在構建時將jar的maven版本號,Subversion修訂版和時間戳放入我的清單中。

你可以閱讀在標準的Java API調用運行清單的內容 - 是這樣的:

import java.util.jar.*; 

... 

JarFile myJar = new JarFile("nameOfJar.jar"); // various constructors available 
Manifest manifest = myJar.getManifest(); 
Map<String,Attributes> manifestContents = manifest.getAttributes(); 

對我來說,感覺就像一個更多的Java標準的方法,這樣很可能會被證明更容易讓後續代碼維護人員需要遵循。

1

除非您想通過C/C++預處理器(這是一個BIG NO-NO)運行Java源代碼,否則使用jar方法。還有其他方法可以從jar中獲取正確的資源,以確保某人不會在類路徑中放置重複資源。你也可以考慮使用Jar清單。我的項目正在使用清單完成你想要做的事情(包括構建日期,修訂版本,作者等)。

你要使用這樣的:

Enumeration<URL> resources = Thread.currentThread().getContextClassLoader().getResources("META-INF/MANIFEST.MF"); 

這將讓大家在類路徑中體現的。你可以通過解析URL來找出他們可以從哪個jar中獲得。

2

AFAIK沒有辦法用javac來做到這一點。這很容易用Ant完成 - 我會創建一個名爲BuildTimestamp.java的第一個類對象,並在編譯時通過Ant目標生成該文件。

Here's an Ant type這將有所幫助。

1

就我個人而言,我會爲你的jar中的一個單獨的屬性文件在運行時加載......類加載器具有用於搜索文件的已定義順序 - 我記不起它是如何工作的,但我不認爲類路徑中某個具有相同名稱的文件可能會導致問題。

但是,另一種方法是使用Ant將.java文件複製到不同的目錄中,然後編譯它們,根據需要過濾字符串常量。你可以使用類似的東西:

public String getBuildDateTime() { 
    return "@[email protected]"; 
} 

並在你的Ant文件中寫入一個過濾器,用build屬性替換它。

0

一個建議,我從同事 得到的是讓螞蟻文件創建classpath中的 文件,並打包 說成JAR,並經 方法讀取。 ...在我看來,這是一個 黑客攻擊,可以通過某人在JAR之外具有類似名稱的 文件但在 類路徑中的人繞過/破壞 。

我不確定讓Ant生成一個文件是一個非常令人震驚的黑客,如果它根本就是黑客。爲什麼不生成屬性文件並使用java.util.Properties來處理它?

1

也許更爲Java風格的指示庫版本的方法是將版本號添加到JAR的清單中,如manifest documentation中所述。

10

我記得看到在一個開源項目類似的東西:在一個模板文件

class Version... { 
    public static String tstamp() { 
    return "@[email protected]"; 
    } 
} 

。隨着螞蟻的過濾副本,你可以給這個宏的值:

<copy src="templatefile" dst="Version.java" filtering="true"> 
    <filter token="BUILDTIME" value="${build.tstamp}" /> 
</copy> 

使用它來創建你的構建過程中Version.java源文件,編譯步驟之前。

相關問題