Showing posts with label mercurial. Show all posts
Showing posts with label mercurial. Show all posts

Saturday, November 30, 2013

Java EE 7 Tip of the Day: Web Application Lifecycle Listeners

Introduction

I have been trying to come up with a way to highlight these fascinating classes in a way that demonstrates their power and usefulness. In my post Java EE 7 Tip of the Day: Programmatic Control of Session Tracking with ServletContextListener I highlighted the use of the ServletContextListener to set session tracking programmatically. However, there are a number of listener classes that can help you. Here they are in generally decreasing scope:

Web Application Lifecycle Listeners

ServletContainerInitializer

The ServletContainerInitializer is a special case that must be registered with the Service Provider Interface (SPI) loading mechanism. Please see the Javadocs for more details on its usage. That is a topic for a different post.

ServletContextListener

The ServletContextListener has been previously mentioned in another post as noted above. This listener is notified of lifecycle changes, e.g. context initialized and destroyed. This gives the developer the opportunity to perform application setup such as setting a logger, or enabling other listeners. It also provides a clean mechanism to handle application cleanup when an application is shutdown, or disabled.

ServletContextAttributeListener

The ServletContextAttributeListener listens for events that occur when attributes are added, modified, or removed from the ServletContext. This could be used to modify those attributes, or perhaps log them. Interestingly, the order in which the implementations are invoked is not specified.

HttpSessionListener

The HttpSessionListener listens for session creation, and destruction events. I have found this to be one of the most useful classes in a web application. This can be used to set up a persistent data connection while the session is valid, and close the connection when the session expires, or is invalidated.

The listener implementations are invoked in the order of declaration, and destroyed in reverse order. A way to think of this is like the layers of filo dough. If you go from top to bottom, then you must reverse order from bottom to top.

HttpSessionAttributeListener

The sibling interface HttpSessionAttributeListener is the second most used class in my toolbox for listeners behind the ServletContextListener and HttpSessionListener. I have found that I often need to examine when attributes are added, modified, or removed from a session. This is the tool I use to manage that.

Keep in mind that the HttpSessionAttributeListener behaves like the ServletContextAttributeListener in that the order in which the implementations are invoked is unspecified. This means that you can not rely on a specified ordering to take place across containers. Usually, the ordering is consistent on a container basis, but the contract is explicit that the ordering is undefined.

HttpSessionIdListener

This is a new to Java EE 7. The HttpSessionBindingListener is used to handle when a HttpSession ID changes. This is usually the result of a HttpServletRequest.changeSessionId() command. This was added in Java EE 7 to help solve a security issue called Session Fixation. Typically, you would change the session id after the user successfully authenticates. This can help you with this transition. Otherwise, you need to do a lot of work to make it happen. In this case, it is just great to be able to let the API handle it.

This interface will allow you to modify your application based on the ID change. Please note that the order in which the implementations are invoked is not specified.

HttpSessionBindingListener

The HttpSessionBindingListener listens for binding events. This occurs when an object is bound, or unbound from a session. There are a couple of examples from BalusC on Stackoverflow. Here are a couple: Getting SessionScoped bean from HttpSessionListener? and How to access HTTP sessions in Java. These are just a couple of examples on its usage. I personally have never used it directly. I was just thinking I should come up with my own example for it.

ServletRequestListener

The ServletRequestListener is another listener that I use. However its usage is not as frequent as the other aforementioned ones. I usually end up checking the ServletRequest with an instanceof for HttpServletRequest and casting it. This listener will allow you to modify an individual request.

Since it has every request pass through it, you should make sure that there is no excessive overhead in the listener such as database lookups, or excessive logging. Abuse of this listener can result in massive performance issues.

ServletRequestAttributeListener

Finally, we have the ServletRequestAttributeListener that listens for request attribute changes. The same warning as noted in the ServletRequestListener applies here. Any excessive overhead will result in dramatic performance decreases.

Like the other attribute listeners, this listener does not have a specific order in which they are invoked.

Code Examples

The code for this project was developed using NetBeans 7.4, Apache Maven, Mercurial, and is hosted on Bitbucket. The code in the examples is somewhat contrived, but does demonstrate the functionality of the listeners.

I strongly recommend downloading the code, executing it, and looking at the output. It will give you a better picture of how the code works, and also show you some hidden "features" of your application that you may be unaware of.

The source code can be downloaded from here: web-application-listeners.

ServletContextListenerImpl.java



ServletContextAttributeListenerImpl.java



HttpSessionListenerImpl.java



HttpSessionAttributeListenerImpl.java



ServletRequestListenerImpl.java



ServletRequstAttributeListenerImpl.java


Conclusion

Web application lifecycle listeners are essential tools for the web developer. If you are not using them, you should consider them to simplify your web development. Hopefully the explanations and code provided help you along your path to becoming a great developer.

Monday, March 25, 2013

Patterns for Scaling Mercurial and Git

I just finished reading over the Refcard Git Patterns and Anti-PatternsScaling from Workgroup to Enterprise by Luca Milanesio from GerritForge. He has done a great job describing patterns and anti-patterns that don't just apply to Git, but any distributed source control system. The obvious focus of this Refcard is Git, but the patterns are essentially the same sans the commands.

I thought that the card was well done, and is a nice and easy read.

Friday, March 22, 2013

Installing Mercurial 2.5.2 on IIS 7.5 and Python 2.7 64-bit

I have been given a great opportunity to move our current source control system from ClearCase to Mercurial. This includes using Active Directory for authentication and authorization. There are a number of great blog posts which helped me along the way. Please see the References at the bottom of the blog. However, I found that none of them were complete, or used older versions of the software.

Prerequisites

  • Microsoft Windows 2008 Server R2, or Microsoft Windows 7
    Note: If you are using Active Directory, the server must be a part of the domain.
  • Internet Information Server (IIS) 7.5
  • Python 2.7.3 (X86-64)
  • Mercurial 2.5.2 (X86-64)

Installation Process

Install Python

Download and install Python 2.7.3 X86-64 using the installer.

Install Mercurial

Download and install Mercurial 2.5.2 (X86-64) for use with Python 2.7.

Note: Do not install TortoiseHg. It is not required, and these directions will not work.

Install Internet Information Server (IIS)

Using the Server Manager on Windows 2008 Server R2, you need to add a role to install IIS. It is not as intuitive as it should be. On other versions of Windows, you would add it as a service.
  1. Add a Server Role.
  2. Select IIS Role.
  3. Select Role Services.
    • Application Development
      • CGI
      • ISAPI Extensions
      • ISAPI Filters
    • Security
      • Basic Authentication
      • Windows Authentication
      • Request Filtering
  4. Installation Complete

Install and Configure CGI (hgweb.cgi)

  1. Clone the mercurial repository, and copy the hgweb.cgi application to located in the project root to C:\Python27\Lib\site-packages\mercurial\hgweb.
    hg clone http://selenic.com/repo/hg
    
  2. Create a hgweb.config in C:\Python27\Lib\site-packages\mercurial\hgweb. Here is an example file:
    [web]
    encoding = UTF-8
    allow_push = *
    push_ssl = False
    contact = John Yeary
    allowzip = True
    
    [paths]
    test = C:\repos\test
    
  3. Modify the hgweb.cgi file to use the new configuration.
    #!/usr/bin/env python
    #
    # An example hgweb CGI script, edit as necessary
    # See also https://www.mercurial-scm.org/wiki/PublishingRepositories
    
    # Path to repo or hgweb config to serve (see 'hg help hgweb')
    config = "hgweb.config"
    
    
    # Uncomment and adjust if Mercurial is not installed system-wide
    # (consult "installed modules" path from 'hg debuginstall'):
    #import sys; sys.path.insert(0, "/path/to/python/lib")
    
    # Uncomment to send python tracebacks to the browser if an error occurs:
    #import cgitb; cgitb.enable()
    
    from mercurial import demandimport; demandimport.enable()
    from mercurial.hgweb import hgweb, wsgicgi
    application = hgweb(config)
    wsgicgi.launch(application)
    

Setup IIS Python CGI Handler

  1. Add a Virtual Directory to the Default Web Site
    • Alias: hg
    • Physical Path: C:\Python27\Lib\site-packages\mercurial\hgweb
  2. Select Handler Mapping from the newly created hg virtual directory.
  3. Click Actions --> Add Script Map
  4. Set the following parameters:
    • Request Path: *.cgi
    • Executable: C:\Python27\python.exe -u "%s"
    • Name: Python
  5. Restart IIS Server

Create Mercurial Test Repository

c:\>mkdir repos

c:\>cd repos

c:\repos>mkdir test

c:\repos>cd test

c:\repos\test>hg init

c:\repos\test>echo "THIS IS A TEST FILE" > README

c:\repos\test>hg add README

c:\repos\test>hg commit -u jyeary -m "Initial Import"

c:\repos\test>hg summary
parent: 0:d5c9f65c740a tip
 Initial Import
branch: default
commit: (clean)
update: (current)

Test Configuration

Using a browser, go to http://localhost/hg/hgweb.cgi. You should see the following:

Here is the changeset for the initial import

URL Rewrite (OPTIONAL)

If you want a cleaner URL for users, you will want to "prettify" your URLs. Luckily, Microsoft has a URL Rewrite plugin for IIS. You will want to install it from the link provided.
Here is the configuration for our application:
  1. Select URL Rewrite from the hg virtual directory.
  2. Create a new blank rule.
  3. Create a Rule with the following parameters:
    • Name: hgweb.cgi
    • Match URL:
      • Using: Wildcards
      • Pattern: *
    • Conditions
      • Add Condition
      • Condition Input: {REQUEST_FILENAME}
      • Check if input string: Is Not A File
    • Action
      • Action Type: Rewrite
      • Rewrite URL: hgweb.cgi/{R:1}
  4. Apply Changes
  5. Modify the hgweb.config and add the baseurl attribute.
    [web]
    encoding = UTF-8
    baseurl= /hg
    allow_push = *
    push_ssl = False
    contact = John Yeary
    allowzip = True
    
    [paths]
    test = C:\repos\test
    
The URL should be much easier now http://localhost/hg/test/

Basic Authentication (Active Directory> for push (OPTIONAL)

The default setup from the hgweb.config allows push from all clients. If we want to add more security, we need to specify authentication, and who is allowed to push.

Note: Basic Authentication passes username and password in clear text. You should use Basic Authentication in conjunction with SSL.

In the default configuration provided, you can push back any changes as shown below.
C:\Users\jyeary\Desktop>hg clone http://localhost/hg/test
destination directory: test
requesting all changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
updating to branch default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved

C:\Users\jyeary\Desktop>cd test

C:\Users\jyeary\Desktop\test>ls
README

C:\Users\jyeary\Desktop\test>touch FILE1

C:\Users\jyeary\Desktop\test>touch FILE2

C:\Users\jyeary\Desktop\test>hg add FILE1

C:\Users\jyeary\Desktop\test>hg add FILE2

C:\Users\jyeary\Desktop\test>hg commit -u jyeary -m "Added files."

C:\Users\jyeary\Desktop\test>hg push
pushing to http://localhost/hg/test
searching for changes
remote: adding changesets
remote: adding manifests
remote: adding file changes
remote: added 1 changesets with 2 changes to 2 files
We will configure our application and the server to use authentication.
  1. Select the hg virtual directory.
  2. Select Authentication
  3. Select Basic Authentication and Enable it.
  4. Edit the settings for your Active Directory (AD) domain.
    • Domain: THIS IS YOUR AD DOMAIN
    • Realm: You can call this anything that you like, I personally use the domain name.
  5. You have set up the authentication, but it still will allow you to push files as demonstrated below.
    C:\Users\jyeary\Desktop\test>touch FILE3
    
    C:\Users\jyeary\Desktop\test>hg add FILE3
    
    C:\Users\jyeary\Desktop\test>hg commit -u jyeary -m "Added FILE3"
    
    C:\Users\jyeary\Desktop\test>hg push
    pushing to http://localhost/hg/test
    searching for changes
    remote: adding changesets
    remote: adding manifests
    remote: adding file changes
    remote: added 1 changesets with 1 changes to 1 files
    
  6. To enable push to require authentication, we need to modify the hgweb.config file. We will modify allow_push = *, and set it to allow push from only certain individuals.
    [web]
    encoding = UTF-8
    baseurl= /hg
    allow_push = jyeary
    push_ssl = False
    contact = John Yeary
    allowzip = True
    
    [paths]
    test = C:\repos\test
    

    Since we have set push to accept only jyeary, it will ask us to authenticate and shown below.
    C:\Users\jyeary\Desktop\test>touch FILE4
    
    C:\Users\jyeary\Desktop\test>hg add FILE4
    
    C:\Users\jyeary\Desktop\test>hg commit -u jyeary -m "Added FILE4"
    
    C:\Users\jyeary\Desktop\test>hg push
    pushing to http://localhost/hg/test
    searching for changes
    http authorization required
    realm: mydomain.com
    user: jyeary
    password:
    remote: adding changesets
    remote: adding manifests
    remote: adding file changes
    remote: added 1 changesets with 1 changes to 1 files
    

Enable SSL (OPTIONAL)

I am indicating that this is optional, but if you are using Basic Authentication; it really should be required. This shows how to create a simple self-signed certificate. In a production environment, you will want to have a certificate signed by Certification Authoritity (CA).
  1. Select the server, and select Server Certificates.
  2. Create a self-signed certificate.

  3. Right-click on the Default Web Site, and select Edit Bindings.
  4. Select Add a Binding
  5. Add an SSL binding as follows:
    • Type: https
    • Port: 443
    • SSL Certificate: selfSigned
  6. Modify the hgweb.config file, and remove the push_ssl = False line.
  7. Test the new configuration by cloning the secured repository
    Note: Unless you add the certificate fingerprint to your hgrc, you will need to use the --insecure flag with mercurial.
    C:\Users\jyeary\Desktop>hg clone --insecure https://localhost/hg/test
    warning: localhost certificate with fingerprint e5:32:64:97:6e:10:43:e5:c7:71:92:9f:08:20:e9:4d:54:d6:c3:04 not verified (check hostfingerprints or web.cacerts config setting)
    
    destination directory: test
    requesting all changes
    adding changesets
    adding manifests
    adding file changes
    added 4 changesets with 5 changes to 5 files
    warning: localhost certificate with fingerprint e5:32:64:97:6e:10:43:e5:c7:71:92:9f:08:20:e9:4d:54:d6:c3:04 not verified (check hostfingerprints or web.cacerts config setting)
    
    updating to branch default
    5 files updated, 0 files merged, 0 files removed, 0 files unresolved
    

Conclusion

Setting up Mercurial is easy to do in a Windows environment. You will gain all of the great benefits from Mercurial along with active directory. It is much easier to setup Mercurial on IIS for use with Active Directory than on a LAMP stack with winbind, or LDAP. If AD is a requirement... this is definitely the solution.

References

Saturday, January 07, 2012

Using Apache HTTPD (Web Server) mod_proxy with GlassFish and Mercurial

I wrote an article on how to use Secure Mercurial in GlassFish using SSL a few weeks ago. After the article was published, I was asked about URL rewriting. I had not really messed with it in the past except with PrettyFaces (which works like a champ for reference).

I tried a framework called Url Rewrite Filter which did a decent job of rewriting URLs. It is a simple library added to your project which uses a servlet filter to handle the URL re-writing. Add the filter to the web.xml, and a urlrewrite.xml which handles the rewrites. It works much in the same manner as PrettyFaces, but is targeted at JSP/Servlets.

In my case, I have an Apple G5 PPC which is the main server for my source repository for Mercurial. This presents some challenges since the Java version is limited to 1.5, and therefore GlassFish can't be upgraded to v3 from v2.1.1. I did manage to get GlassFish v3 to run with OpenJDK 1.7 (BSD Port), but the Zero VM is too slow to handle the load. Kurt Miller has a couple of the builds for Mac PPC There are a number of reasons for my interest, the primary one for URL rewriting is that GlassFish v3 supports AJP out of the box.

Enabling JK Listener (mod_jk)

Using GlassFish v3 would provide a more optimal solution as you can see from the administration console. I decided to try using the mod_jk articles I found for GlassFish v2 from Amy Roh: GlassFish supports configurable AJP Connector and Jean-Francois Arcand's Running GlassFish with Apache httpd.  I tried to combine these with mod_proxy and mod_proxy_ajp. The articles are focused on a specific build, and I was unsuccessful in using them. I am sure it has to framework versions, but I did not want spend too much time troubleshooting.

Finally, I tried using a simple mod_proxy arrangement along with mod_rewrite. This arrangement was surprisingly easy to configure, and worked the first time I tried it.

Here is the configuration I used:

httpd.conf



httpd-vhosts.conf


Those simple changes allowed me to rewrite the URL, and open only two ports on my firewall 80 and 443 which are a very good arrangement. As noted in Secure Mercurial in GlassFish using SSL, I am using GlassFish SSL and security to handle my authentication so this is truly a very good solution.
Mercurial Repositories

Wednesday, December 14, 2011

Subversion to Mercurial Migration: Using --splicemap to Map Branches and Merges

I am in the process of migrating all of my existing code projects to Mercurial from Subversion. However, the process has some snags associated with it. The biggest snag is that Mercurial does not understand the branching and merging process which is common in most Subversion repositories.  If you convert a repository from Subversion to Mercurial the timeline indicates the branch, but does not associate it with the parent (default head). This results in "floating" heads (branches). One blogger I found called it a multi-headed Hydra.

Floating Heads (Branches)

What we really want is to show consistency, and progression. We want to show the branches and merges that are stored Subversion in Mercurial. We don't want to lose that vital historical information.

So we now know what the problem is, but how do we fix it. It turns out that the convert extension method has a very poorly (read not useful at all) documented switch called splicemap. This allows us to map specific revisions in parent-child relationships.

In the Rock Hymas blog, they give an example of the format for our splicemap for Subversion. It looks like the following:
svn:<uuid>/path/to/module@revnum
However, he ends short of what to do with this information, or how to obtain it. The article is good on explanation of the issue, but not on how to solve it. I will detail a solution and show you how I did it. I will also show how to use a splicemap "so that others may live"... oh wait that is the US Air Force Pararescue motto. I will show a working example to make a point.

Process

The first thing we will need is the UUID from Subversion. This can be obtained using the svnlook command.
apple1:~ root# svnlook uuid /usr/local/svnhome/
dbc3d074-2bd0-48a6-aa6f-e69526dc1c92
The UUID is absolutely vital. It will be different for every repository.

Next, we need a log of the activity for the project we are interested in mapping. We will use the svn log -v command to get the details. The results will look something like this.  I have shortened my output to just a couple of relevant versions which we will need.

------------------------------------------------------------------------
r417 | jyeary | 2011-12-11 06:28:21 -0500 (Sun, 11 Dec 2011) | 1 line
Changed paths:
   M /MailService/trunk/MailService/build.xml
   M /MailService/trunk/MailService/nbproject/build-impl.xml
   M /MailService/trunk/MailService/nbproject/genfiles.properties
   A /MailService/trunk/MailService/nbproject/jaxws-build.xml
   M /MailService/trunk/MailService/nbproject/project.properties 
  
Merged 3.0 tag to trunk, and updated NetBeans project files. 
------------------------------------------------------------------------
r137 | jyeary | 2008-09-05 19:15:25 -0400 (Fri, 05 Sep 2008) | 1 line
Changed paths:
   M /MailService/branches/3.0-DEV/MailService/src/java/com/bluelotussoftware/mail/ee/ssb/MailServiceBean.java

Updated properties.
------------------------------------------------------------------------
r128 | jyeary | 2008-09-02 17:51:49 -0400 (Tue, 02 Sep 2008) | 1 line
Changed paths:
   M /MailService/trunk/MailService
   M /MailService/trunk/MailService/nbproject/project.properties
   M /MailService/trunk/MailService/src/conf/sun-ejb-jar.xml
   D /MailService/trunk/MailService/src/java/com/bluelotussoftware/mail/ee/ssb/MailService.java
   M /MailService/trunk/MailService/src/java/com/bluelotussoftware/mail/ee/ssb/MailServiceBean.java
   D /MailService/trunk/MailService/src/java/com/bluelotussoftware/mail/ee/ssb/MailServiceRemote.java
   A /MailService/trunk/MailService/src/java/com/bluelotussoftware/mail/ee/ssb/local (from /MailService/branches/2.0-DEV/MailService/src/java/com/bluelotussoftware/mail/ee/ssb/local:124)
   R /MailService/trunk/MailService/src/java/com/bluelotussoftware/mail/ee/ssb/local/MailServiceLocal.java (from /MailService/branches/2.0-DEV/MailService/src/java/com/bluelotussoftware/mail/ee/ssb/local/MailServiceLocal.java:124)
   A /MailService/trunk/MailService/src/java/com/bluelotussoftware/mail/ee/ssb/remote (from /MailService/branches/2.0-DEV/MailService/src/java/com/bluelotussoftware/mail/ee/ssb/remote:124)
   R /MailService/trunk/MailService/src/java/com/bluelotussoftware/mail/ee/ssb/remote/MailServiceRemote.java (from /MailService/branches/2.0-DEV/MailService/src/java/com/bluelotussoftware/mail/ee/ssb/remote/MailServiceRemote.java:124)

merged 2.0 changes into trunk.
------------------------------------------------------------------------

Next we determine how to splice it together. We want to ensure that the parents, and children match up.  The file format is: child parent with a space between the child and parent. We may also provide an additional parent which is separated by a comma such as child parent1,parent2

So the first splice in the splicemap for the 2.0-DEV branch looks like this:

svn:dbc3d074-2bd0-48a6-aa6f-e69526dc1c92/MailService/branches/2.0-DEV@95 svn:dbc3d074-2bd0-48a6-aa6f-e69526dc1c92/MailService/trunk@57

Note: I am splicing the branch to the trunk (parent).

Using the hg convert --datesort --splicemap splicemap1 http://10.0.1.2/svn/MailService resulted in the following output:

assuming destination MailService-hg
initializing destination MailService-hg repository
svn: cannot probe remote repository, assume it could be a subversion repository. Use --source-type if you know better.
scanning source...
sorting...
converting...
21 creating structure
20 Moving project out of MailServiceApplication
19 Fixed javadoc
18 [Netbeans SVN client generated message: create a new folder for the copy]: '
spliced in ['svn:dbc3d074-2bd0-48a6-aa6f-e69526dc1c92/MailService/trunk@57'] as parents of svn:dbc3d074-2bd0-48a6-aa6f-e69526dc1c92/MailService/branches/2.0-DEV@95
17 2.0 development branch
16 1. Updated version numbers.
15 Added new sendMessage() method that allows for different MIME types.
14 1.Added new MimeMessage format to @Remote
13 1.Added new MimeMessage format to @Local
12 1. Added new MimeMessage format
11 Updated project properties
10 1. Created a new local package
9 1. Updated Javadocs
8 Updated project properties
7 merged 2.0 changes into trunk.
6 Adding new development branch
5 Adding trunk to 3.0 Development branch
4 Removed @Local interface implementation from bean.
3 Removed @Local interface.
2 Removed directory.
1 Updated properties.
0 Merged 3.0 tag to trunk, and updated NetBeans project files.
updating tags

More importantly, the result is what we are looking for. See the image below.

Branch
Alright, that solved the branching problem, but the more difficult issue is the merge. I was banging my head on my desk when I came across this Nabble post by Bruce Frederiksen which gave me the clue I needed to merge the branch back to the default head.

We need to tell Mercurial what the parent branches are for the merge from the perspective of the repository. In this case we want the revision at 57 as one parent from the branch above, and the other to be the revision we merge at on the default head. In this case revision 123. We also need to reverse the order (remember what I said about perspective... thanks Bruce). Our new splice looks like:

svn:dbc3d074-2bd0-48a6-aa6f-e69526dc1c92/MailService/branches/2.0-DEV@95 svn:dbc3d074-2bd0-48a6-aa6f-e69526dc1c92/MailService/trunk@57
svn:dbc3d074-2bd0-48a6-aa6f-e69526dc1c92/MailService/trunk@127 svn:dbc3d074-2bd0-48a6-aa6f-e69526dc1c92/MailService/trunk@57,\
svn:dbc3d074-2bd0-48a6-aa6f-e69526dc1c92/MailService/branches/2.0-DEV@123

Note: I am splicing the trunk@127 to the trunk@57 and branch@123. This is the trick.

Note: The splices are wrapped to fit on the page, the actual file requires each complete splice to be on a new line.

The result when we run the hg convert command again results in merging  the branch back to the default head.

Branch-Merge
Finally, I make the remaining splices to complete the mapping which look like:

svn:dbc3d074-2bd0-48a6-aa6f-e69526dc1c92/MailService/branches/2.0-DEV@95 svn:dbc3d074-2bd0-48a6-aa6f-e69526dc1c92/MailService/trunk@57
svn:dbc3d074-2bd0-48a6-aa6f-e69526dc1c92/MailService/trunk@127 svn:dbc3d074-2bd0-48a6-aa6f-e69526dc1c92/MailService/trunk@57,\
svn:dbc3d074-2bd0-48a6-aa6f-e69526dc1c92/MailService/branches/2.0-DEV@123
svn:dbc3d074-2bd0-48a6-aa6f-e69526dc1c92/MailService/branches/3.0-DEV@129 svn:dbc3d074-2bd0-48a6-aa6f-e69526dc1c92/MailService/trunk@128
svn:dbc3d074-2bd0-48a6-aa6f-e69526dc1c92/MailService/trunk@417 svn:dbc3d074-2bd0-48a6-aa6f-e69526dc1c92/MailService/trunk@128,\
svn:dbc3d074-2bd0-48a6-aa6f-e69526dc1c92/MailService/branches/3.0-DEV@137

Note: The splices are wrapped to fit on the page, the actual file requires each complete splice to be on a new line.

This results in the final completed completed product.

Completed

Conclusion

I hope that this explains how to effectively use a splicemap to branch and merge your Subversion repository into Mercurial. I hope that this saves some other unfortunate developers from trying to figure out a really cool, but poorly documented feature of the convert extension.

Tuesday, December 13, 2011

Secure Mercurial in GlassFish using SSL

A friend of mine, Wade Chandler, contacted me the other day to ask about implementing security (SSL) for Mercurial on GlassFish. Wade is NetBeans Dream Team member, and all-around great guy. I told him I would figure it out, and tell him how to do it. I also decided that I would explain to everyone how to take advantage of this cool functionality using GlassFish 3.1.1 and NetBeans 7.1 RC 2. 

In  a previous blog entry, Mercurial on GlassFish 2.1 Using Multiple Repositories, I successfully deployed Mercurial repositories on GlassFish. This time I have given everything a Java EE 6 upgrade.

One of the great aspects of using GlassFish to provide SSL is that we don't require messy configuration in Python and Mercurial to implement SSL. GlassFish handles the security for us. The only thing that the end client users will want to do is add the server fingerprint to the .hgrc file in their home directory. This will remove any warnings about a missing server fingerprint, or cacerts file.

If you have used Mercurial on Apache HTTPD Server, along with cacerts, and client certificates... this will make you make the switch immediately.

Requirements:

You can create your own web project in NetBeans, but the Mercurial.zip is a self-contained Mercurial repository, and NetBeans project which can serve as the basis for your own server with very little modification. I would simply use my project as the basis for your own deployment.

Note: The requirements include repos.zip which is optional. The repos.zip contains sample mercurial repos which are required for the demo.

Procedures

Configure GlassFish

  1. Start the GlassFish administration console.
  2. Go to Configurationserver-configSecurityRealmsfile.
    Note: You may create your own realm, this is just for demonstration purposes.
  3. Click on Manage Users.
    GlassFish Security Configuration
  4. Click on New. Add a user called mercurial in a group called Mercurial Users with the password hg.
    Note: Please change the username, group, and password for production.
  5. The server configuration is complete.

NetBeans

  1. Using NetBeans open the Mercurial project from the requirements link above.
  2. There are four files in the project (simple huh?) which control the behavior of the Mercurial repository on GlassFish: hgweb.cgi, hgweb.config, web.xml, and glassfish-web.xml.
  3. The hgweb.cgi should not need to be modified under normal circumstances.
  4. Open the hgweb.config file. Make any changes that you would like to customize the application. Pay particular attention to the location of the repositories.
    There are two examples: (1) using the "/" along with a * on the end of the file path will list all repositories in the specified directory, and (2) a specific listing.

    Note: Please note that allow_push = * and push_ssl = false are set. This will allow push to the server and let GlassFish take care of the SSL.
  5. The web.xml file has been modified to add security constraints for the alpha, and beta example repositories.
    The alpha repository has security only on PUT, POST, and DELETE.
    The beta repository will not allow you to perform any actions without logging into the server.
    The gamma repository has no security constraints.

    Note: You will need to modify the security constraints to meet your requirements.

    Note: You secure the entire repository by adding:
    <url-pattern>/cgi-bin/hgweb.cgi/*</url-pattern>.

  6. The glassfish-web.xml is used to map the security role(s) to the file realm on the GlassFish server.
  7. Clean, build, and Run the application.
  8. When the application successfully deploys, go to the secure connection on https://localhost:8181/Mercurial. It may prompt you to accept the server certificate. Accept it.
  9. You should see something like the image below:
    Mercurial Repositories
  10. Click on the beta repository. It should prompt you to login.
  11. Congratulations you are running Mercurial on GlassFish securely.

Note: To secure the application completely, you should disable the non-secure http port listener on port 8080, or redirect requests to the secure port. 

Verification

It would be unwise to accept that the application is secure without verification.

I made this demonstration video to prove the connection is secure. The demonstration shows both insecure and secure connections to the repository. I use Wireshark to sniff the connection, and pull the repository from the command line using hg clone.


Conclusion

Mercurial is a great distributed source control system. Its ease of use is further enhanced by using GlassFish 3.1.1 to provide the front end to your repository. It also simplifies the deployment, and use models.

Friday, May 01, 2009

Mercurial on GlassFish 2.1 Using Multiple Repositories

Introduction

In this tutorial I explain the basics of creating multiple Mercurial repositories, and then configuring GlassFish 2.1 to connect and display them. Mercurial is an open source source control system. GlassFish is an open source Java™ application server. I will not explain how to install Mercurial, nor GlassFish. The respective sites have excellent documentation on how to install them.

Creating Repositories

1. Create a directory called /repos.

2. Using the command prompt, navigate to the /repos directory and issue the following commands.
hg init alpha
hg init beta
hg init omega
This will create three new Mercurial repositories.

3. Change to the respective repositories and add a file called hgrc to the .hg directory. This file should contain a contact and a description of the repository. Here is a representative example from my alpha repository.

[web]
contact = John Yeary <jyearyATbluelotussoftwareDOTcom>
description = Alpha source code repository.
This information will be displayed on our main page.

NetBeans 6.5

1. Using NetBeans create a new Project -> Java Web ->Web Application.

2. Call the project Mercurial.



3. The default Context Path is the project name. We will change it from /Mercurial to /mercurial.



4. Click Finish. This will create a basic web project which will compile to a nice WAR file for deployment on GlassFish.

5. We will begin to modify our project by removing the index.jsp file.

6. Next go to the Web Pages -> WEB-INF directory. In here you will find the default web.xml file. Open it in the editor.

7. Follow the directions from Jean-Francois Arcand's Blog on Enabling CGI support in GlassFish. An example of my web.xml file is displayed below. This will enable the CGI servlet which is used by Mercurial to display the repositories.
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>cgi</servlet-name>
<servlet-class>org.apache.catalina.servlets.CGIServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>cgiPathPrefix</param-name>
<param-value>WEB-INF/cgi</param-value>
</init-param>
<load-on-startup>5</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>cgi</servlet-name>
<url-pattern>/cgi-bin/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

8. Next we will create a sub-directory WEB-INF called cgi. This will contain our CGI applications.

9. Obtain a copy of the source code for your version of Mercurial. Locate the hgwebdir.cgi file and copy it to your WEB-INF/cgi directory.

10. Create a file called hgweb.config in the WEB-INF/cgi directory. The hgwebdir.cgi application expects this file to exist and point to your repositories. The hgwebdir.cgi file contains help on configuring the file. Here is an example configuration based on our setup.

[paths]
/ = /repos/*

This will allow the hgwebdir.cgi to map all repositories located in the /repos directory.

11. Next we modify the web.xml file and change the welcome files list to point to the application.
<welcome-file-list>
  <welcome-file>cgi-bin/hgwebdir.cgi</welcome-file>
</welcome-file-list>
12. Click on Run and you should be delighted to see the following.


Issues

If you encounter any errors, or nothing appears, you can enable debugging for python by un-commenting the following lines in the hgwebdir.cgi file.
# Uncomment to send python tracebacks to the browser if an error occurs:
#import cgitb
#cgitb.enable()
You may also enable debugging on the cgi application by changing the debug parameter to 1 in the web.xml file
<init-param>
<param-name>debug</param-name>
<param-value>1</param-value>
</init-param>

Here is a copy of my NetBeans Mercurial Project. It is itself a Mercurial repository.

Popular Posts