DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Newsletter
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

The Latest DevOps and CI/CD Topics

article thumbnail
Ant or Gant?
Yes, this is exactly what I am frequently asked by my clients and many developers. It isn't easy to answer this question. There are several projects using Ant. Should you run away from Ant just because there is a new cool tool out there called Gant? Should you switch to Gant just because you dislike XML? Not at all. Let's take a closer look and see what might make you switch to Gant. When to choose Gant? 1. Complicated Build Files. If your ant build files are becoming too complicated, and hard to manage, it's time to see if using Gant can help. Let me explain what I mean by complicated build files. If you have too much of conditional logic within your build files, say something similar on the lines shown below in Listing 1: Code Listing 1: Or even something like this where you might be supporting deployment to different application servers based on some property in your build.properties as shown in listing 2. Code Listing 2: Things get out of hand when you have conditional logic as shown above in your build scripts. The listings I have are just the skeleton, imagine what happens when we start adding the actual deployment logic for all these application servers. It doesn't matter how you refactor this, it is still going to be very complicated. Trust me, I have written build scripts which were several thousand lines, and refactoring them was not a trivial task. 2. Custom Ant Tasks. I myself am guilty of writing many of these. There are many situations which arise in projects where we create custom ant tasks. It is simple once you know how to write one, and than for every complicated task you need to perform, you involuntarily will start writing custom ant tasks. Anyone writing a custom ant task will: a. Create a new class that extends Ant’s org.apache.tools.ant.Task class. b. For each attribute, write a setter method. c. Write an execute()method that does what you want this task to do. There isn't anything wrong in doing the above, but imagine each time you want to make a small change, you will have to make changes within your Java source code, compile, test, and re-package. 3. Scripting. You can extend Ant further by not writing custom ant tasks, but by using small snippets of code written in an interpreted language like JRuby, BeanShell, or Groovy. These code snippets can be placed within your build files or in separate text files. If you are using Groovy's Ant task, your build file might look something like this: Code Listing 3: import some.package import another.package def fullpath = "${.basedir}/${defaulttargetdir}" def somefile = new SomeFile(projectName:"${pname}", buildLabel:"${label}", buildTime:"${new Date()}") def xml = "${fullpath}/dashboard.xml" new File(path).write(somefile.generateReport()) ant.xslt(in:path, out:"${properties.defaulttargetdir}/some.html", style:"${properties.defaulttargetdir}/lib/report-style.xsl") Imagine having several lines of XML in your build files which have many of these small snippets of scripts. I myself don't like mixing and matching build files with code snippets. If you have a team where everyone is in the same page, everything works fine. What if a team member has no clue about any of the Scripting languages? He/She will have no clue how to make minor changes when things go badly. If you have all the above or even one of the above three cases, you seriously need to consider using Gant. To quote Aristotle: For the things we have to learn before we can do them, we learn by doing them." So, lets see how easy it is to learn Gant and see how things can improve. This part covers the very basics of Gant. The next part, will dive deeper into Gant by using it with a sample project to build an application, and we will also see how to use it with our CI Server. What's Gant? Gant is a build tool that uses both Groovy and Ant. With Gant, you describe your build process using Groovy scripts. Stated simply, Gant allows you to specify the build logic using Groovy instead of XML. The next thing you may ask is " Is Gant a competitor to Ant?". Let me quote from the Gant web site to make thing more clear here : Whilst it might be seen as a competitor to Ant, Gant uses Ant tasks for many of the actions, so Gant is really an alternative way of doing builds using Ant, but using a programming language rather than XML to specify the build rules. Download and Install Gant. In order for Gant to work, you should have Groovy installed. You can download and follow the installation instructions for Groovy here. As I said earlier also, in order to use Gant, you should have knowledge of Groovy as well. If you have never written Groovy code before, there are many interesting books on Groovy like: 1. Groovy in Action 2. Groovy Recipes 3. Groocy Refcardz You can also read the getting started guide on the Groovy web site, which should give you a good starting point. Download the latest version of Gant from here. Gant is currently at version 1.4.0. Unzip it to a folder. If you already have your GROOVY_HOME set, that's all you need to use Gant. Getting Started. Open a console, and type gant. You should see a message as shown below: meera-subbaraos-macbook-9:~ meerasubbarao$ gant Cannot open file build.gant meera-subbaraos-macbook-9:~ meerasubbarao$ You are all set at this point to use Gant in your projects. Help Information: Open a console, and type gant -h. This will provide you with all the necessary help information you need as shown below: meera-subbaraos-macbook-9:CodeMetricsProject meerasubbarao$ gant -h usage: gant [option]* [target]* -c,--usecache Whether to cache the generated class and perform modified checks on the file before re-compilation. -n,--dry-run Do not actually action any tasks. -C,--cachedir The directory where to cache generated classes to. -D = Define to have value . Creates a variable named for use in the scripts and a property named for the Ant tasks. -L,--lib Add a directory to search for jars and classes. -P,--classpath Specify a path to search for jars and classes. -T,--targets Print out a list of the possible targets. -V,--version Print the version number and exit. -d,--debug Print debug levels of information. -f,--file Use the named build file instead of the default, build.gant. -h,--help Print out this message. -l,--gantlib A directory that contains classes to be used as extra Gant modules, -p,--projecthelp Print out a list of the possible targets. -q,--quiet Do not print out much when executing. -s,--silent Print out nothing when executing. -v,--verbose Print lots of extra information. Create a new file called build.gant at the root of your project. Did a similarity between Ant and Gant strike you here? Ant build files are usually called build.xml, and they are created as a common practice within the root of your project folder as well. If you have written or even modified Ant build files, you will know that it contains one project element, which in turn contains a name,the default target and the base directory. Code Listing 4: So for example, sayHello target in Ant would look something like this: Lets create the sayHello target, and also see how to set it as the default target in Gant as well. A Gant target has a name and a description: Code Listing 5: target ( target-name : target-description ) { groovy code sequence } The above sayHello target in Gant would translate as shown below: target(sayHello:"Saying hello"){ Ant.echo(message:"Hello Javalobby") } Now, open a command window and type gant at the root of the project where the build.gant file exists. You should be able to see a output like: meera-subbaraos-macbook-9:CodeMetricsProject meerasubbarao$ gant Target default does not exist. Gant is complaining that we haven't set a Default target. Lets see how to do the same: Default target: Within Ant, you define the default target from within the project element as seen in Listing 4. The default target is the target called if no target is specified from the command line. There however is no project tag within Gant. There are two ways of specifying the default target as shown below: 1. You simply create a target whose name is default. target ( 'default' , 'The default target.' ) { aTarget ( ) 2. or even simply: setDefaultTarget ( aTarget ) In order to get our sayHello target working, we need to add one of the above scripts to our build.gant file. Code Listing 6: setDefaultTarget(sayHello) or target ("default": "The default target." ) { sayHello ( ) } Complete listing of build.gant: target(sayHello:"Saying hello"){ Ant.echo(message:"Hello Javalobby") } /* target ("default": "The default target." ) { sayHello ( ) } */ setDefaultTarget(sayHello) And you should be able to see: meera-subbaraos-macbook-9:CodeMetricsProject meerasubbarao$ gant [echo] Hello Javalobby meera-subbaraos-macbook-9:CodeMetricsProject meerasubbarao$ That was easy! If you have build files and it is becoming unmanageable by your team, there is a tool out there which can convert your Ant scripts to Gant scripts as well. I haven't used it, but you can try it here. In this part of the series, we learned when to move over from Ant to Gant, downloaded and installed Gant, and finally wrote a simple gant build file. In the next part of this series, we will see Gant in Action within a simple Java project. And as always, keep us posted here if you are encountering any problems getting started with Gant. Stay tuned.
September 23, 2008
by Meera Subbarao
· 52,479 Views
article thumbnail
Javadoc or Doxygen?
In the last two articles, "Reverse-engineer Source Code into UML Diagrams" and "Visual Documentation of Ant Dependencies in 3 Simple Steps" we saw how easy and valuable it was to automate technical documentation. By using open source tools, we were easily able to provide good technical documentation within a few minutes, and at no cost at all. We were also able to keep this up-to date by adding additional tasks to our Ant build files, and run them from our CI Server(Hudson in our case) on commit and nightly builds, and also publish the results. In this article, I will be showing you how to use yet another tool called Doxygen for generating technical documentation based on your source code. We all have used Javadoc and have been using it for a long time, right? So, you may ask what's the need to have another tool which produces the same HTML documentation? Doxygen has a slight edge over Javadoc and here are a few reasons why you should consider using the same: With Javadoc you have to remember all the HTML tags, you need to embed within your code comments. However, with Doxygen code comments are much more concise and polished, without the need for any HTML. Doxygen can also generate a variety of diagrams, we will take a look at some of them later. Doxygen also provides a structured view on the source code. As I mentioned in 2 above in the form of various diagrams, cross-referenced and syntax highlighted code. You get all the above benefits even if the code does not have any comments at all. Last but not the least, Doxygen is a documentation system not for just Java but also for various other languages like C++, C, Java, Objective-C, Python, IDL (Corba and Microsoft flavors), Fortran, VHDL, PHP, C#. So, without wasting further time, lets see what we need to get started with Doxygen. Step 1. Download, Install Doxygen. Download the binary distribution for Doxygen for the operating system you are using. I downloaded the binary distribution for Mac OS X called Doxygen-1.5.6.dmg. Installation is very simple, just drag the doxygen icon from this folder to the Applications folder, or wherever you want to keep it; as shown. I dropped it within my Applications folder. Just be sure to remember where you dragged it. To uninstall, just delete the file. It is completely self-contained. Step 2: Configure Doxygen. To generate documentation using Doxygen, you will need a configuration file called the Doxyfile. You can generate this file in two ways; either by using the Doxygen wizard or by using the command line option. Lets see how to use both these options to generate the configuration file: a. Command line. Open a command window and type the following as shown below: You should be able to locate the configuration file created within your default user folder. The file looks like this: # Doxyfile 1.5.6 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = b. Wizard Option. Launch the Doxygen application, and you should be able to create the configuration file using the wizard approach as shown below. The user interface is quite intuitive so I am going to skip explaining this in detail. The wizard approach was the one I used to get the initial settings for the configuration file. which you can always modify later. A few options in my Doxygen configuration file are as follows: # Doxyfile 1.5.6 #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = PetStore PROJECT_NUMBER = 1.0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- EXTRACT_ALL = NO EXTRACT_PRIVATE = NO EXTRACT_STATIC = NO EXTRACT_LOCAL_CLASSES = YES #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- GENERATE_HTML = YES HTML_OUTPUT = html HTML_FILE_EXTENSION = .html GENERATE_TREEVIEW = YES Step 3. Doxygen and Ant. In order to use Doxygen, we need an Ant task. There is already an Ant task written for Doxygen which you can download from here. As always, since using Mac, when I downloaded the binaries and tried to use them, I got the ever famous error message : java.lang.UnsupportedClassVersionError: Bad version number in .class file So, had to do download the source, compile, and jar it up. Copy this library to your projects folder. Next, lets start making changes to our build file. 3.a: Lets define the Doxygen task. 3.b: To generate HTML documentation: 3.c: Lets combine them in target and run: [doxygen] Exec: /Applications/Doxygen.app reports/Doxyfile BUILD FAILED /CodeMetricsProject/build.xml:91: Doxygen not found on the PATH. Total time: 7 seconds 3.d: So, to launch Doxygen not in the path. we make change to the doxygen task as shown below: Lets run the target again and see if it fixed things.Yes indeed. generate-doxygen-docs: [doxygen] Exec: /Applications/Doxygen.app/Contents/Resources/doxygen reports/Doxyfile BUILD SUCCESSFUL Total time: 8 seconds 4. Integrate with Hudson. 4.a Modify Hudson Job. Once you have an Ant target working, calling this from your CI server is trivial. Within Hudson, select your Job, click on configure and add this new target to be called when running the build. 4.b Publish the reports. 4. c: Sample Reports. Force a build, and take a detailed look at the reports generated by Doxygen as shown below: I have given you a brief overview of Doxygen in this article, how to configure the same, and use it effectively to generate technical documentation on a continuous basis; either on commit builds or nightly builds. The Doxygen web site has lots of information on how to use it with other programming languages and also has tutorials in languages other than English as well. As always, if you are having trouble getting Doxygen to work, leave a comment or check out the Doxygen web site.
September 10, 2008
by Meera Subbarao
· 49,986 Views · 1 Like
article thumbnail
Reverse-Engineer Source Code into UML Diagrams
This article shows how easy and simple it is to include UML diagrams within your Javadoc and also keep them updated with every change in the source code repository.
August 22, 2008
by Meera Subbarao
· 221,232 Views · 1 Like
article thumbnail
Ant Build File Changes for Java Web Projects in NetBeans IDE 6.1
While working with a Java Web Application in NetBeans, I noticed some slight changes in the Ant build file for my project between NetBeans 6.0 and 6.1. This article explores some of the problems these changes caused to help out anyone with similar issues. I started with a Java Web Application that was created in NetBeans 6.0.1. After adding some JSP files and several Java source files, I committed everything in the project to my CVS repository. For some of my projects, I utilize the Hudson continuous integration build server. Using a standard deployment of Hudson, I configured the project to poll the SCM every 60 minutes, check out the code from CVS (if changes had been committed), and trigger the NetBeans project’s Ant build file (calling several specific targets like compile, dist, and so on. My builds have been functioning correctly for several weeks using this standard setup. I recently opened one of those projects in NetBeans 6.1 Beta and have been thoroughly enjoying the new features (faster startup, better JSP parsing in the Source Editor). After adding some JAR files as libraries and making several configuration changes, I committed the entire project (particularly the build-related files in the nbproject directory). Suddenly, my build for that project started failing. The console output reported by Hudson was : -init-check: BUILD FAILED D:/projects/hudson-server/data/jobs/MyWebProjectl/workspace/nbproject/build-impl.xml:149: The Java EE server classpath is not correctly set up. Your active server type is Tomcat55. Either open the project in the IDE and assign the server or setup the server classpath manually. For example like this: ant -Duser.properties.file= (where you put the property “j2ee.platform.classpath” in a .properties file) or ant -Dj2ee.platform.classpath= (where no properties file is used) Total time: 2 seconds finished: FAILURE I undid the configuration changes one by one, but the build failed regardless of what I reset. Apparently the property j2ee.platform.classpath is now required. I did a DIFF on the nbproject/build-impl.xml file and discovered several changes. The -init-check target includes property checks including this new one : The Java EE server classpath is not correctly set up. Your active server type is ${j2ee.server.type}.Either open the project in the IDE and assign the server or setup the server classpath manually.For example like this: ant -Duser.properties.file= (where you put the property “j2ee.platform.classpath” in a .properties file) or ant -Dj2ee.platform.classpath= (where no properties file is used) I hadn’t really taken notice of this property in the build file before, but it is referenced in a number of other targets such as: -init-macrodef-javac, -init-macrodef-junit, -init-macrodef-java, -init-macrodef-nbjpda, -init-macrodef-debug, compile-jsps, -do-compile-single-jsp, connect-debugger, javadoc-build, -do-compile-test, -do-compile-test-single Not being able to find a definition of the property anywhere in the build file, I looked through the project’s project.properties file among the list of defined properties. The property j2ee.platform.classpath was not defined. Thus, I’m assuming this is passed into the build file dynamically by NetBeans? In general I wouldn’t care, but when running the build file via Ant inside Hudson, the property j2ee.platform.classpath is never passed in. Hudson DOES allow you to pass properties and values to the build file, so I suppose I can specify the value manually, but I would like to keep the number of per project customizations to a minimum to maintain a low level of maintenance. Unless this causes some problem with the project properties in the build system, I would suggest the following fix for anyone who is experiencing a similar issue. Open your project’s project.properties file. Navigate to the section that contains these properties: j2ee.platform=1.4 j2ee.server.type=Tomcat55 Add a new line that specifies a blank j2ee.platform.classpath property such as this: j2ee.platform=1.4 j2ee.platform.classpath= j2ee.server.type=Tomcat55 Now, if the project.properties file is committed to CVS, a Hudson build can be triggered, and the FAIL check in the build-impl.xml file will pass. I ran some quick tests with the project, and everything with the project inside NetBeans still seems to work fine. I would propose to the NetBeans team to have the j2ee.platform.classpath property automatically added to the project.properties file.
March 26, 2008
by Adam Myatt
· 15,784 Views
article thumbnail
DJ NativeSwing - reloaded: JWebBrowser, JFlashPlayer, JVLCPlayer, JHTMLEditor.
Today's release of DJ Native Swing 0.9.4 greatly improves stability and brings new components: in addition to the JWebBrowser and JFlashPlayer, there is now the JVLCPlayer and the JHTMLEditor. Here is a summary of what to expect when using this library. 1. Various native components DJ Native Swing was designed to handle all the complexity of native integration, mainly in the form of components with a simple Swing-like API. Here are some screenshots of several components in action (click to enlarge): JWebBrowser: JFlashPlayer: JVLCPlayer: JHTMLEditor: 2. Simple API First, we need to initialize the framework. This needs to happen before any feature is used. A common place for this call is the first line of the main(): public static void main(String[] args) { NativeInterfaceHandler.init(); // Here goes the rest of the initialization. } Now, let's see how to create a JWebBrowser, with its URL set to Google's homepage: JWebBrowser webBrowser = new JWebBrowser(); webBrowser.setURL("http://www.google.com"); myContentPane.add(webBrowser); Note that we set a URL, but we could as well set the HTML text. The JWebBrowser also allows to execute Javascript calls, and we can even propagate notifications from custom pages to our Swing application. Moving to a more practical example, we may want to be notified of URL change events or track window opening events, potentially preventing navigation to occur or open the page elsewhere. This is easily achieved by attaching a listener: webBrowser.addWebBrowserListener(new WebBrowserAdapter() { public void urlChanging(WebBrowserNavigationEvent e) { String newURL = e.getNewURL(); if(newURL.startsWith("http://www.microsoft.com/")) { // Prevent the navigation to happen. e.consume(); } else { // We can consume the event and decide to open this page in a tab. } } public void windowWillOpen(WebBrowserWindowWillOpenEvent e) { // We can prevent, add the URL to a tab, etc. } // There are of course more events that can be received. }); Let's have a look at the JFlashPlayer: JFlashPlayer flashPlayer = new JFlashPlayer(); flashPlayer.setURL(myFlashURL); The JFlashPlayer can open local or remote Flash files, and files from the classpath; the latter being a general capability of the library by proxying files using a minimalistic web server. Of course, the JFlashPlayer allows to retrieve and set Flash variables, and play/pause/stop the execution. The JVLCPlayer and the JHTMLEditor are no exceptions to this simplicity: playlist can be manipulated in the VLC player, HTML can be set and retrieved from the HTML editor, etc. There is also the possibility to integrate Ole controls on Windows, still with a simple Swing-like API. An example is provided in the library in the form of an embedded Windows Media Player. 3. Advanced capabilities The library takes care of most common integration issues. This covers modal dialog handling, Z-ordering, heavyweight/lightweight mix (to a certain extent), invisible native components with regards to focus handling and threading. Here are some more screenshots, showing a lightweight/heavyweight mix, and Z-ordering capability: The demo application that is part of the distribution shows all the features along with the source code, so check it out! 4. Project info and technical notes Webstart demo: http://djproject.sourceforge.net/ns/DJNativeSwingDemo.jnlp Screenshots: http://djproject.sourceforge.net/ns/screenshots Native Swing: http://djproject.sourceforge.net/ns The DJ Project: http://djproject.sourceforge.net The 0.9.4 version has a completely new architecture. It still uses SWT under the hood, but it does not use the SWT_AWT bridge anymore. The JWebBrowser and browser-based components require XULRunner to be installed, except on Windows when using Internet Explorer. The JVLCPlayer requires VLC to be installed. The JHTMLEditor uses the FCKeditor. 5. Conclusions This project finally brings all that is needed to make Java on the desktop a reality. A web browser, a flash player, a multimedia player, and even an HTML editor. So, what next? Yes, what next? For that one, I am waiting for your feedback. So, what do you think? What are your comments and suggestions? -Christopher
March 12, 2008
by Christopher Deckers
· 54,708 Views
article thumbnail
SVNKit: Tame Subversion with Java!
SVNKitis an Open Source pure Java Subversion library. SVNKit literally brings Subversion, popular open source version control system, to the Java world. With SVNKit you can do the following: All standard Subversion operations: For instance, the following snipped checks out project from repository: File dstPath = new File("c:/svnkit"); SVNURL url = SVNURL. parseURIEncoded("http://svn.svnkit.com/repos/svnkit/branches/1.1.x/"); SVNClientManager cm = SVNClientManager.newInstance(); SVNUpdateClient uc = cm.getUpdateClient(); uc.doCheckout(url, dstPath, SVNRevision.UNDEFINED, SVNRevision.HEAD, true); Updates it to the latest revision: uc.doUpdate(dstPath, SVNRevision.HEAD, true); And finally commits local changes in "www" subdirectory if there are any: SVNCommitClient cc = cm.getCommitClient(); cc.doCommit(new File[] {new File(dstPath, "www")}, false, "message", false, true); SVNKit supports all standard Subversion operations and compatible with the latest version of Subversion. Access Subversion repository directly: Some applications will benefit from working with repository directly, without keeping working copy locally. Example below displays list of files in "www" directory. SVNURL url = SVNURL.parseURIEncoded("http://svn.svnkit.com/repos/svnkit/branches/1.1.x/"); SVNRepository repos = SVNRepositoryFactory.create(url); long headRevision = repos.getLatestRevision(); Collection entriesList = repos.getDir("www", headRevision, null, (Collection) null); for (Iterator entries = entriesList.iterator(); entries.hasNext();) { SVNDirEntry entry = (SVNDirEntry) entries.next(); System.out.println("entry: " + entry.getName()); System.out.println("last modified at revision: " + entry.getDate() + " by " + entry.getAuthor()); } Direct repository access API allows to perform operations like update, commit, diff and many other. Additionaly to the performance benefits of the direct access to repository, this API makes it possible to version arbitrary objects or object models within Subevrsion repository, not only files from the file system. Replace JNI Subversion bindings with SVNKit: Native Subversion provides Java interface that works with Subversion binaries through JNI. In case you already using it or would like to use as an option, you may also use SVNKit through exactly the same interface. This way you'll let your application dynamically switch between JNI and SVNKit implementation of the same API or let your application work on the platforms where there are no native Subversion binaries. For example: // pure Java implementation of the standard Subversion Java interface SVNClientInterface jniAPI = SVNClientImpl.newInstance(); byte[] contents = jniAPI.fileContent("http://svn.svnkit.com/repos/svnkit/branches/1.1.x/changelog.txt", Revision.HEAD); SVNKit is widely used in different applications, including IntelliJ IDEA, Eclipse Subversion integrations, SmartSVN, JDeveloper, bug tracking server side applications (e.g. Atlassian JIRA) and repository management and tracking tools (e.g. Atlassian FishEye) and many others. Where to get more information: Recently we've released SVNKit version 1.1.6 which is bugfix release. At http://svnkit.com/ you will find more information on that new version and, of course, downloads, documentation, source code example and articles explaining how to use SVNKit. In case of any questions you're welcome at our mailing list, or just contact us at [email protected] SVNKit is widely used in different applications, including IntelliJ IDEA, Eclipse Subversion integrations, SmartSVN, JDeveloper, bug tracking server side applications (e.g. Atlassian JIRA) and repository management and tracking tools (e.g. Atlassian FishEye) and many others. With best regards, TMate Software, http://svnkit.com/ - Java [Sub]Versioning Library!
February 26, 2008
by Alexander Kitaev
· 11,424 Views · 2 Likes
  • Previous
  • ...
  • 335
  • 336
  • 337
  • 338
  • 339
  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook
×