I have the data for my webapp in a database that is accessed differently from different places. There is no generic code that can just do it for both. So I want to know at run time which env I am in. In fact, the code to run really depends on whether it is run within or without tomcat, so I would like to detect this at runtime. How do I do this?
This doesn't sound like something that the code should have to detect. Placing the burden of detecting an environment and acting differently within the same class is usually a less-than-ideal idea. If things need to be done differently, you should make a couple of different data access classes (which implement the same interface, and maybe share common code in an abstract class they both extend). Then, your web servlet would instantiate and use one class for its database access, and your non-web code would instantiate the other class for database access.
If for some reason you REALLY need to detect whether or not you're in the web abb within a single class, I suppose a somewhat clean way might be to set a System property when the server runs (I think it's -D command line option), and then look for that being set in your class. If it is, do the web logic, otherwise do the non-web logic.
I would agree with kbrasee that this isn't a great situation to be in, so if you can I would get out it if possible.
That said, assuming you have no choice and need to do this, they do it in the Liferay implementation. Have a look at the ServerDetector class
You'll notice in the _detect method (near the bottom) that they look for a class that they have determined is present if it is running in the given server. They define the classes at the top in the TOMCAT_BOOTSTRAP_CLASS and TOMCAT_EMBEDDED_CLASS constants.
We had a problem with it detecting the embedded tomcat within glassfish. I'm not sure if that's fixed in the version I linked to, but it may not be a problem for you.
If this is not for a quick hack right now, but for a long term solution then please notice that any heuristic you choose to make a decision which has not been put in an API stone, will eventually break. The whole point of OSGi is to hide unrelated parts of the stuff in the JVM from each other.
I think for this particular situation the best way to see if you are inside Tomcat or not, is to see if there is a JNDI environment available. If not, you are in a stand alone environment, if there is then you are inside Tomcat.
Well, all the well heeded warning aside, I would like to throw my $0.02 in the discussion.
I think ServerDetector uses the presence of a particular class on the system classpath to determine the type of running server is a little flawed: what if the jar containing the class just happened to be on the classpath but is not used? I propose a different method of detecting the running server by using stack trace elements. It might not be perfect but I think it's better than detecting the presence of some class on the classpath.
Here it is in Scala:
def inTomcat: Boolean = (new Throwable).getStackTrace.exists(_.getClassName.startsWith("org.apache.catalina"))