|  | <!doctype html public "-//w3c//dtd html 4.0 transitional//en"> | 
|  | <html> | 
|  | <head> | 
|  | <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> | 
|  | <meta name="Author" content="Eclipse Project"> | 
|  | <title>Flexible Project Structure</title> | 
|  | <link rel="stylesheet" href="../../default_style.css" type="text/css"> | 
|  | </head> | 
|  | <body bgcolor="#FFFFFF" > | 
|  |  | 
|  | <div align="left"> | 
|  | <h1>Flexible Project Structure</h1> | 
|  | </div> | 
|  | <blockquote> | 
|  | <p><b>Summary</b> <br> | 
|  | Eclipse requires that the contents of each project be stored in a single directory on disk. | 
|  | Every file and folder in that directory tree on disk must belong to the project in the workspace. | 
|  | This restriction makes it difficult to use Eclipse in conjunction with tools that have specific layout | 
|  | requirements for their files, or with users who have legacy file base layouts that they need | 
|  | to maintain. We would like to improve the situation for the 2.1 release of Eclipse. This document | 
|  | is the third of a trilogy.  The first described the | 
|  | <a href="http://www.eclipse.org/eclipse/development/inflexible-projects-problem.html"> | 
|  | nature of the problem</a>, and the second mapped out the various | 
|  | <a href="http://www.eclipse.org/eclipse/development/towards-more-flexible-projects.html"> | 
|  | options for addressing it</a>.  This third document describes the concrete proposed solution | 
|  | in detail.<br><br> | 
|  | Last Modified: 18:30 October 24, 2002</p> | 
|  | </blockquote> | 
|  | <hr/> | 
|  | <h2>Overview</h2> | 
|  | <p> | 
|  | Analysis of the problem identified three characteristics of Eclipse projects that made them | 
|  | difficult to use in conjunction with existing project layouts.  Namely, Eclipse projects are | 
|  | currently <b>single-rooted</b>, <b>all-inclusive</b>, and <b>non-overlapping</b>. | 
|  | The proposed solution includes a new mechanism in the Platform core for allowing projects | 
|  | to be multi-rooted, a new JDT facility for interacting with a selective subset of a project, and a relaxation | 
|  | of the restriction that resources cannot overlap in the file system.  For readers of the previous | 
|  | document that mapped out the solution space, these are solutions P-2, Q-1, M-2, S-2, V-1 | 
|  | and V-2. | 
|  | </p> | 
|  | <p> | 
|  | Relaxing these restrictions is necessarily a breaking change for many tools built on the Eclipse platform. | 
|  | Some plug-ins may be able to adapt to the new behavior in future releases, but some may never | 
|  | work in the presence of projects that relax these layout restrictions.  To minimize the impact, the | 
|  | proposed solution adheres to the following principles: | 
|  | <ul> | 
|  | <li>Only expose the new functionality in the contexts where flexibility problems have been reported. | 
|  | For example, users will be able to change the location of JDT source folders and the output folder, | 
|  | but not be able to change the location of folders at arbitrary depths.  Exposure of the new flexibility can | 
|  | be widened to fit new contexts where compelling use cases arise. | 
|  | <li>Cause no breakage for projects that maintain the old constraints.  That is, if a user's project | 
|  | continues to be single-rooted, all-inclusive, and non-overlapping, then all plug-ins should continue | 
|  | to function with no code changes needed.</li> | 
|  | <li>Maintain binary compatibility with 2.0- and 1.0-based plug-ins.</li> | 
|  | </ul> | 
|  | </p> | 
|  | <p> | 
|  | These solutions will not fundamentally change the workspace resource model.  The workspace | 
|  | still maintains a faithful representation of corresponding files on the local disk.  Local refresh will | 
|  | still cause the workspace to be updated to accurately reflect the changed contents on disk.  Operations | 
|  | on resources in the workspace will continue to have direct impact on files in the file system -- deletion | 
|  | from the workspace will cause deletion of files from disk, etc.  Directories on disk that are associated with | 
|  | resources in the workspace will continue to "belong" to the workspace, and this association | 
|  | will still be recursively all-inclusive.  Projects will still have a single, non-overlapping root directory. | 
|  | The only significant change is that a project can now attach contents that are not in its root directory. | 
|  | This allows a single project to bring together contents from several different directories on disk. | 
|  | </p> | 
|  | <hr/> | 
|  | <h2>1. Multi-Rooted Projects</h2> | 
|  | <p> | 
|  | Two categories of problems were identified in relation to the single-rootedness of Eclipse projects. | 
|  | The most common complaint is that it is impossible to locate the Java builder's output folder | 
|  | in another location.  The other complaint is that users wanted to draw together sources from several | 
|  | locations into a single project.  This second case arises commonly for users of the Eclipse JDT, but also | 
|  | for users of the CDT (C/C++ tools project).  In general, this problem boils down to allowing the project to | 
|  | contain folders located elsewhere in the file system. | 
|  | </p> | 
|  | <h3>New Platform Core API</h3> | 
|  | <p> | 
|  | Part of the proposed solution is to add new API in the Platform core to allow <i>linking</i> | 
|  | external resources into projects (solution M-2 from the previous document).  This will | 
|  | allow clients of the workspace API to logically connect a resource sub-tree located outside | 
|  | of the project's content area into a project. | 
|  | </p> | 
|  | <p> | 
|  | The <code>link</code> operation is invoked on an IFile or IFolder handle in a fashion similar | 
|  | to the <code>create</code> method.  That is, it must be called on a resource that does | 
|  | not yet exist, and the result of the operation is that the resource (and possibly child | 
|  | resources) exists. No files or folders in the file system are moved or modified as | 
|  | a result of creating the link.  The link operation essentially just creates resources in the | 
|  | Eclipse workspace tree corresponding to all files at the given file system location. | 
|  | Similarly, deletion of a link removes the corresponding resources from | 
|  | the workspace tree, but leaves the files in the file system untouched.  The new terms | 
|  | <i>linked folder</i> and <i>linked file</i> (generally, <i>linked resource</i>) will be used | 
|  | to describe these new entities.  This document will also use the term <i>link location</i> | 
|  | to refer to the file system path corresponding to a given linked resource. Children of linked | 
|  | folders are <b>not</b> referred to as linked resources. | 
|  | </p> | 
|  | <p> | 
|  | Support will only be added for linking resources as direct children of a project.  Restricting | 
|  | links to only the first level makes the model easier to understand for clients and | 
|  | users.  Essentially, the project becomes a logical container that can have arbitrary resources | 
|  | linked in, and the semantics of other files and folders remain the same.  None of the other IDEs surveyed | 
|  | allowed linking external resources at arbitrary depths.  Finally, supporting links | 
|  | at arbitrary depths would add significant complexity to the implementation, and would affect the | 
|  | performance of most "deep" workspace operations such as deletion, local refresh, move, etc. | 
|  | </p> | 
|  | <h4>Copy, move and deletion of linked resources</h4> | 
|  | <p> | 
|  | Links will have similar semantics to soft symbolic links in Unix.  Copy and move semantics are as follows: | 
|  | <ul> | 
|  | <li>If a linked resource is copied or moved into another project, a new linked | 
|  | resource will be created in the destination project that points to the same | 
|  | location.</li> | 
|  | <li>Copying or moving a linked resource into another folder will not be permitted | 
|  | (since links must be direct children of projects). The UI could offer to do | 
|  | a deep copy/move of all resources in this case ("Linked resources can | 
|  | only exist immediately below projects. Do you want to copy/move the contents | 
|  | of the underlying files into /x/y/z?").</li> | 
|  | <li>If a linked resource is renamed, it will continue to be a linked resource | 
|  | pointing to the same location.</li> | 
|  | <li>If a resource contained within a linked folder is copied or moved, it will | 
|  | be copied or moved in the file system in the normal way. No links will be | 
|  | created or deleted.</li> | 
|  | <li>If a project containing linked resources is copied or moved, the new project | 
|  | will contain linked resources to the same locations.</li> | 
|  | </ul> | 
|  | Deletion semantics: | 
|  | <ul> | 
|  | <li>Deletion of a linked resource will never delete the contents on disk. This | 
|  | is symetrical to the behavior of link creation: you cannot create the target | 
|  | of a linked resource from within Eclipse, and you cannot delete the target | 
|  | of a linked resource from within Eclipse. We will add a flag for deleting | 
|  | the contents of the linked resource in the file system, but it will not be | 
|  | the default behaviour of the <code>delete</code> operation.</li> | 
|  | <li>Deletion of a resource contained within a linked folder will cause the underlying | 
|  | files to be deleted from disk in the normal way.</li> | 
|  | <li>Deletion of a project containing a linked resource will also never delete | 
|  | the contents of the linked resource on disk.</li> | 
|  | </ul> | 
|  |  | 
|  | <h4>Pre-validation of link locations</h4> | 
|  | <p> | 
|  | A new validation method (<code>IWorkspace.validateLinkLocation</code>) will be introduced | 
|  | to allow clients to check if a proposed file system location is an acceptable location to link into the | 
|  | workspace.  This method will return a status with severity <code>IStatus.ERROR</code> if the | 
|  | proposed location is not acceptable (for example, if it contains characters that Eclipse does not | 
|  | allow in filenames, or if it overlaps the workspace metadata area).  The method will return a | 
|  | status with severity <code>IStatus.WARNING</code> if the proposed location overlaps | 
|  | another resource location in the workspace.  The section on overlapping resources will | 
|  | discuss this in more detail. | 
|  | </p> | 
|  | <h4>Persistence of link data</h4> | 
|  | <p> | 
|  | Link locations will be represented by entries in the .project file.  Modifying the .project file | 
|  | can cause links to be created or deleted.  A new kind of Core path variables will | 
|  | be introduced, and link locations can be relative to these variables.  Resources will be | 
|  | created for all links described in the .project file, even if they cannot be accessed (for | 
|  | example if based on an undefined variable or location that is not accessible). | 
|  | </p> | 
|  | <h4>Facility for disabling links</h4> | 
|  | <p> | 
|  | There may be some plug-ins that, for whatever reason, do not want to tolerate links | 
|  | in projects they operate on.  For example, a web site management tool may | 
|  | rely on the file system structure of a project being the same as the structure in the | 
|  | resource tree.  A mechanism will be introduced to allow plug-ins to prevent | 
|  | links from being added to a given project. | 
|  | </p> | 
|  | <p> | 
|  | An attribute will be added to project natures that specifies whether the nature | 
|  | allows links.  This will default to being true (links allowed), if the | 
|  | nature does not specify it.  If any nature installed on a project does not allow | 
|  | links, then attempts to create links will fail.  Attempting to install a nature | 
|  | that does not allow links on a project that already has links will fail. | 
|  | </p> | 
|  | <p> | 
|  | Additionally, a hook will be added so that team providers have an opportunity to disallow | 
|  | links.  Team providers based on 2.0 will <b>not</b> allow links on projects that they | 
|  | manage.  Team providers based on 2.1 or greater must specify that they tolerate links. | 
|  | </p> | 
|  | <p> | 
|  | If either of these mechanisms decides to veto links, users will not be | 
|  | able to override this decision (except by removing the intolerant plug-in). | 
|  | </p> | 
|  |  | 
|  | <h3>Implications for team providers</h3> | 
|  | <p> | 
|  | Generally, links will be ignored by team providers.  The assumption is that | 
|  | these files are generally taken from some location outside the workspace because they are | 
|  | already managed by an external VCM tool. The java output folder is also usually of | 
|  | no interest to VCM tools.  Team providers that have been upgraded to Eclipse 2.1 | 
|  | will be expected to silently tolerate and ignore links.  This includes handling of links in the team | 
|  | move/delete hook.  If team providers wish to provide more support for linked resources, | 
|  | they may do so.  As mentioned earlier, team providers based on Eclipse 2.0 will not | 
|  | tolerate the presence of links on projects they manage. | 
|  | </p> | 
|  |  | 
|  | <h3>Platform UI Changes</h3> | 
|  | <p> | 
|  | The Platform UI will add new operations to allow users to create links as top | 
|  | level folders and files.   It may be useful to provide a warning in the UI when linking is | 
|  | first attempted to warn users that this may cause problems for other plugins (A warning | 
|  | dialog with the option, "Don't tell me again" would be appropriate). | 
|  | Linked resources should have some visual annotation in the resource navigator to make it | 
|  | easy to distinguish linked resources from normal resources in the UI. | 
|  | </p> | 
|  | <p> | 
|  | The Platform UI will also add a preference page and dialogs for adding, removing, and editing the platform | 
|  | core variables used in link locations.  This will be similar to the current UI for java classpath variables. | 
|  | </p> | 
|  | <h3>JDT Changes</h3> | 
|  | <p> | 
|  | JDT core will need to revisit compiler and search infrastructure that currently relies | 
|  | on direct navigation of resources in the file system.  Since it is no longer guaranteed that all | 
|  | source folders are children of the project's local directory, they will need to consult the | 
|  | workspace API to find the correct locations. | 
|  | </p> | 
|  | <p>New flexibility will also be added for java output folders, specifically: | 
|  | <ul> | 
|  | <li>Linked output folders can be used for placing build output outside the project location (P-2).</li> | 
|  | <li>Each source folder can specify a separate output folder (Q-1). | 
|  | <li>Multiple projects can use the same output folder.</li> | 
|  | </ul> | 
|  | </p> | 
|  | <p> | 
|  | Allowing multiple projects to share an output folder introduces a new problem.  Currently, each java | 
|  | builder assumes that it has complete control of the output folder.  On full build, it currently deletes the | 
|  | entire output folder, which will obviously not be acceptable in a shared scenario.  If the builder | 
|  | does not delete the output folder before full builds, then any extra .class files in the output | 
|  | folder will influence the classpath of that project.  This can have unexpected results at runtime | 
|  | if stale classes in the output folder obscure legitimate classes in other projects.  Neither approach | 
|  | (scrub everything or scrub nothing) is entirely appealing.  However, a flag will be introduced on | 
|  | output folders to allow either of those two options.  If the user turns scrubbing off, they will | 
|  | have to deal with the problem of performing "make clean" before full builds by themselves. | 
|  | </p> | 
|  | <hr/> | 
|  | <h2>2. Selectively Inclusive Projects</h2> | 
|  | <p> | 
|  | In some of the identified problems, users wanted to operate on only a selected subset | 
|  | of the resources in a project.  There are two different angles to this problem: | 
|  | <ol> | 
|  | <li>Wanting to completely exclude some resources from the Eclipse workspace</li> | 
|  | <li>Wanting to exclude some resources from consideration by certain tools (such as the Java builder)</li> | 
|  | </ol> | 
|  | </p> | 
|  | <p> | 
|  | The first problem is more difficult to address, and would cause more grief for tools that | 
|  | rely on the all-inclusive nature of the workbench.  The difficulty in supporting complete | 
|  | exclusion boils down to tension between plug-ins that have different needs.  One plug-in | 
|  | may wish to exclude certain resources, while another plug-in operating on the same resource | 
|  | tree may not want to exclude those same resources.  Furthermore, external tools that may | 
|  | operate on resources in the workspace (such as Netscape™ or Ant scripts), will not be aware | 
|  | of any resource exclusion mechanism introduced in the platform, and would thus be fundamentally | 
|  | at odds with such a mechanism. | 
|  | </p> | 
|  | <p> For these reasons, support for exclusion will only be introduced at the JDT | 
|  | level. JDT Core will provide a new facility for adding exclusion rules to source | 
|  | classpath entries. These exclusion rules will support matching of path prefixes, | 
|  | e.g., exclude com/xyz/package1/*. Excluded resources will be omitted completely | 
|  | from the Java model, and will not be considered for compilation. These exclusion | 
|  | rules will be stored in the .classpath file, and thus automatically shared with | 
|  | other team members. This approach is equivalent to solution S-2 from the previous | 
|  | document. </p> | 
|  | <hr/> | 
|  | <h2>3. Overlapping Projects</h2> | 
|  | <p> | 
|  | The proposed solution is to have almost no restrictions on overlapping link locations. | 
|  | Existing restrictions on non-overlapping project locations will remain. Linked resources | 
|  | will only have a small number of restrictions to prevent situations impossible to support. | 
|  | This breaks down as: | 
|  | <ul> | 
|  | <li>Project locations cannot overlap other project locations.</li> | 
|  | <li>Link locations can overlap other link locations, and other project locations.</li> | 
|  | <li>Link locations cannot be the same as or a parent of the root directory of the | 
|  | project the link is contained in (this would result in an infinitely recursive project tree).</li> | 
|  | <li>Link locations cannot overlap the workspace metadata area (can also result in | 
|  | infinite recursion of folder structures).</li> | 
|  | <li>The .project file cannot be a linked file (chicken and egg problem | 
|  | because link information is stored in the .project file).</li> | 
|  | </ul> | 
|  | </p> | 
|  | <p> | 
|  | The platform core change will introduce some new behavior and wrinkles | 
|  | in how resources behave.  If two resources correspond to the same underlying | 
|  | file, then changing one resource will incur a resource delta on both.  Also, if a | 
|  | <code>refreshLocal</code> is invoked on an overlapping portion of the workspace, | 
|  | then several different resources may be refreshed as a result.  Because of the potential | 
|  | dangers of having overlapping resources (generally that changing one will affect all duplicates), | 
|  | a warning will be presented when a user tries to create a linked resource whose location | 
|  | overlaps another resource in the workspace.  Calculation of this warning will be done | 
|  | by the new <code>validateLinkLocation</code> method. | 
|  | </p> | 
|  | <p> | 
|  | This change has ramifications for the following Platform Core methods: | 
|  | <br><br><code> | 
|  | IFile IWorkspaceRoot.getFileForLocation(IPath location);<br> | 
|  | IContainer IWorkspaceRoot.getContainerForLocation(IPath location); | 
|  | </code><br><br> | 
|  | The specification of these methods will be clarified to indicate that they will | 
|  | ignore linked resources.  They will continue to only look in each project's root | 
|  | location for the file system path in question. If a given file exists under both a | 
|  | project's root directory and under a link location, it will always return the resource | 
|  | under the project's root directory.  Since project root directories cannot overlap, | 
|  | there is no ambiguity to this solution. New link-aware API methods will be introduced for finding | 
|  | the set of resources corresponding to a given file system location. | 
|  | </p> | 
|  | <h3>JDT Changes</h3> | 
|  | <p> | 
|  | JDT Core will add the ability to introduce nested source folders, subject to the condition | 
|  | that the nested portion is excluded from the parent folder.  Users will not be allowed to | 
|  | link the same folder twice to create two different source folders at the same location in a given project. | 
|  | </p> | 
|  | <hr/> | 
|  | <h2>Examples Redux</h2> | 
|  | <p> | 
|  | To show that the proposed solution is sufficient to solve many of the problems described | 
|  | in the problem definition, we will revisit the four example workspaces from the problem | 
|  | statement and show how they can be supported by the proposals in this document. | 
|  | </p> | 
|  | <p>Example 1:</p> | 
|  | <p> | 
|  | |- AllProducts<br> | 
|  |     |- Product1<br> | 
|  |         |- JavaSourceFiles<br> | 
|  |     |- Product2<br> | 
|  |         |- JavaSourceFiles<br> | 
|  | </p> | 
|  | <p> | 
|  | This configuration can be supported using only the new linked resources. | 
|  | Projects would be left in the default workspace content area, and the source folders | 
|  | would be linked into the monolithic directory tree.  Eclipse artifacts such as .project, | 
|  | along with build output, would remain in the default area, thus causing no pollution | 
|  | of the source tree with transient or Eclipse-specific files.  This solution assumes that | 
|  | the resources are not being managed by an eclipse team provider: | 
|  | <br><br> | 
|  | /Product1 at default location<br> | 
|  |    /src - java source folder linked at file://AllProducts/Product1/JavaSourceFiles<br> | 
|  | /Product2 at default location<br> | 
|  |    /src - java source folder linked at file://AllProducts/Product2/JavaSourceFiles<br> | 
|  | </p> | 
|  | <p> | 
|  | If such a monolithic resource tree needs to use an Eclipse team provider, then an | 
|  | extra project can be used whose location is the "AllProducts" folder.  This | 
|  | extra project would be a simple project without a java builder, and would be used for | 
|  | source control purposes only.  All other projects would not have a team provider. | 
|  | </p> | 
|  | <p> | 
|  | /MasterProject at file://AllProducts (shared with team provider)<br> | 
|  | /Product1 at default location (no team provider)<br> | 
|  |    /src - java source folder linked at file://AllProducts/Product1/JavaSourceFiles<br> | 
|  | /Product2 at default location (no team provider)<br> | 
|  |    /src - java source folder linked at file://AllProducts/Product2/JavaSourceFiles<br> | 
|  | </p> | 
|  |  | 
|  | <p>Example 2:</p> | 
|  | <p> | 
|  | |- AllJavaSourceFiles<br> | 
|  |     |- com<br> | 
|  |         |- xyz<br> | 
|  |             |- product1<br> | 
|  |                 | 
|  | |- P1Main.java<br> | 
|  |             |- product2<br> | 
|  |                 | 
|  | |- P2Main.java<br> | 
|  | </p> | 
|  | <p> | 
|  | This common configuration requires support from all three proposal areas.  Again projects | 
|  | would remain in the default content area, one project per product.  All projects would link | 
|  | the same external folder as a source folder, <tt>AllJavaSourceFiles</tt>.  Each project's source | 
|  | folder would then exclude all other product packages from its build classpath. | 
|  | </p> | 
|  | <p> | 
|  | /Product1 at default location (no team provider)<br> | 
|  |    /src - java source folder linked at file://AllJavaSourceFiles, excluding com/xyz/product2.<br> | 
|  | /Product2 at default location (no team provider)<br> | 
|  |    /src - java source folder linked at file://AllJavaSourceFiles, excluding com/xyz/product1.<br> | 
|  | </p> | 
|  | <p> | 
|  | If such a monolithic resource tree needs to make use of an Eclipse team provider, it | 
|  | can be arranged in a similar fashion to example 1.  An extra project would correspond | 
|  | to AllJavaSourceFiles, and would have an Eclipse team provider installed. | 
|  | </p> | 
|  | <p> | 
|  | /MasterProject at file://AllJavaSourceFiles (shared with team provider)<br> | 
|  | /Product1 at default location (no team provider)<br> | 
|  |    /src - java source folder linked at file://AllJavaSourceFiles, excluding com/xyz/product2.<br> | 
|  | /Product2 at default location (no team provider)<br> | 
|  |    /src - java source folder linked at file://AllJavaSourceFiles, excluding com/xyz/product1.<br> | 
|  | </p> | 
|  | <p>Example 3:</p> | 
|  | <p> | 
|  | |- Product1<br> | 
|  |     |- JavaSourcesFiles<br> | 
|  |         |- com<br> | 
|  |             |- xyz<br> | 
|  |     | 
|  |             |- product1<br> | 
|  |            | 
|  |           | 
|  | |- P1Main.java<br> | 
|  |         |- tests<br> | 
|  |             |- com<br> | 
|  |                 | 
|  | |- xyz<br> | 
|  |            | 
|  |           | 
|  | |- product1<br> | 
|  |              | 
|  |             | 
|  | |- tests<br> | 
|  |                 | 
|  |             |- | 
|  | P1Test.java<br> | 
|  | </p> | 
|  | <p> | 
|  | This directory structure could be supported in several ways, but the most likely solution is as follows. | 
|  | A single project would be created.  The path Product1/JavaSourceFiles/ would be specified as a source folder. | 
|  | This folder would have an exclusion rule to omit the "tests" sub-directory.  The path | 
|  | Product1/JavaSourceFiles/tests would be specified as a second source folder, with no exclusion rules.  If desired, | 
|  | the two source folders could be placed in separate Eclipse projects to provide greater separation between | 
|  | application code and tests. | 
|  | </p> | 
|  | <p> | 
|  | /Product1 at default location <br> | 
|  |    /JavaSourceFiles - java source folder excluding the "tests" sub-directory.<br> | 
|  |       /tests - java source folder<br> | 
|  |  | 
|  | </p> | 
|  | <p>Example 4: </p> | 
|  | <p>|- CommonFramework<br> | 
|  |     |- JavaSourceFiles<br> | 
|  | |- Product1<br> | 
|  |     |- JavaSourceFiles<br> | 
|  | |- Product2<br> | 
|  |     |- JavaSourceFiles<br> | 
|  | </p> | 
|  | <p> | 
|  | Again this structure can be supported in several ways.  The most likely is to create three projects, | 
|  | mapping to CommonFramework, Product1 and Product2.  Product1 and Product2 would create a | 
|  | linked source folder CommonFramework/JavaSourceFiles.   In this case CommonFramework | 
|  | would not need to be a java project, as it mainly just acts as the VCM container for that set of files. | 
|  | <p> | 
|  | /CommonFramework at file://CommonFramework<br> | 
|  | /Product1 at file://Product1<br> | 
|  |    /JavaSourceFiles - java source folder<br> | 
|  |    /src-common - java source folder linked at file://CommonFramework/JavaSourceFiles<br> | 
|  | /Product2 at file://Product2<br> | 
|  |    /JavaSourceFiles - java source folder<br> | 
|  |    /src-common - java source folder linked at file://CommonFramework/JavaSourceFiles<br> | 
|  | </p> | 
|  | </body> | 
|  | </html> |