Jump to: navigation, search

WTP: Consumer Control of Access Rules

Introduction

Access rules are an important part of declaring and documenting a component's API. This is typically done by marking packages as x-internal in the manifest.mf file, and in some cases, declaring your known "friends" with the x-friend directive. In WTP things should be "friends" only if they are in the same feature-component, according to our defined "build features", and as documented in Subsystems and Features.

This conservative approach is done to be useful to adopters, making clear what is not API (yet), but is problematic for WTP itself, since we still have not evolved all our intended API, so even our own code "violate" our API. Of course, these are not very bad violations for WTP, since we'll be releasing everything "in sync" for at least another release or two.

In the mean time, this approach causes too many warnings in the development environment, so the discouraged access warnings have to be turned off or filtered out ... which means we miss important warnings, where we violate someone else's internal packages.

The Solution

There is a capability in the Eclipse Development environment that we in WTP should take advantage of. While, normally, access rules are defined "from below" by the supplied plugins, there is a capability in the IDE to tweak the access rules "from above" so that we, as consumers, can accept certain risks, but still be informed of other violations.

One easy example is that everything in JST can, for now, pretty safely use anything in WST, even though we would not want to declare the WST methods as API (at least yet). So, JST classes using WST classes is an acceptable risk for WTP.

The Method

To tweak the access rules "from above" there are two methods, modify the build path properties using the provided UI, or, "manually" edited the .classpath file ... the UI method is usually recommended, and the .classpath is a system file, and normally users should not be hand editing those.


The Edit Access Rule UI

Pretty easy once you see where it is.

TweakingAccessRules.jpg


Editing the .classpath file

In some cases, it may be easier to try "hand editing" the .classpath file. It is recommended to use the UI approach at least once, and then once that's working, mimic the changes it made to your .classpath file. The end result would look something similar to the following (this example is from the jst.jsp.ui plugin, which depends on a lot from WST).

<?xml version="1.0" encoding="UTF-8"?>
<classpath>
	<classpathentry kind="src" path="src" />
	<classpathentry kind="con"
		path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.4" />
	<classpathentry kind="con"
		path="org.eclipse.pde.core.requiredPlugins">
		<accessrules>
			<accessrule kind="accessible"
				pattern="org/eclipse/wst/sse/core/**" />
			<accessrule kind="accessible"
				pattern="org/eclipse/wst/xml/core/**" />
			<accessrule kind="accessible"
				pattern="org/eclipse/wst/css/core/**" />
			<accessrule kind="accessible"
				pattern="org/eclipse/wst/html/core/**" />
			<accessrule kind="accessible"
				pattern="org/eclipse/wst/sse/ui/**" />
			<accessrule kind="accessible"
				pattern="org/eclipse/wst/xml/ui/**" />
			<accessrule kind="accessible"
				pattern="org/eclipse/wst/css/ui/**" />
			<accessrule kind="accessible"
				pattern="org/eclipse/wst/html/ui/**" />				
			<accessrule kind="accessible"
				pattern="org/eclipse/wst/javascript/ui/**" />	
			<accessrule kind="accessible"
				pattern="org/eclipse/wst/validation/**" />
			<accessrule kind="accessible"
				pattern="org/eclipse/wst/common/componentcore/internal/util/IModuleConstants" />
		</accessrules>
	</classpathentry>
	<classpathentry kind="output" path="bin" />
</classpath>

Best Practices and Policy in WTP

First, and most important, it would never be appropriate to "hide" discouraged access warnings from any plugins outside of WTP.

Second, it's highly recommended to make the rules as specific as you can ... preferably right down to the specific class or interface. Technically, any JST plugin could simply use a pattern of "org/eclipse/wst/**" but this would not be very informative to others reading your code (and there are others that read your code :), but more important, using the more specific patterns prevents you from making an accidental use of non-api from another plugin. For example, using the JSP UI classpath patterns above, you can see we rely heavily on the other editing components, both UI and core, since this itself is a UI plugin, but we do not depend on many non-API in wst.common.componentcore ... just one Interface, so we list it explicitly. That way if someone should happen to write some code that happened to use another non-api class form wst.common.componentcore, we'd still get a warning about it, and make a considered decision if that was the right thing to do, or not.