Resources en het bestandssysteem

Als het platform en de resourcesplugin actief zijn, wordt het werkgebied aangegeven door een instance van IWorkspace die een protocol biedt voor toegang tot de erin opgenomen resources. Een IWorkspace-instance vertegenwoordigt een gekoppelde collectie bestanden en directory's in een of meer bestandssystemen. U kunt toegang tot het werkgebied krijgen vanuit de resourcespluginklasse (gedefinieerd in org.eclipse.core.resources).

   IWorkspace workspace = ResourcesPlugin.getWorkspace(); 

Als de resourcesplugin niet wordt uitgevoerd, bestaat het werkgebied uitsluitend uit het bestandssysteem en kan het door de gebruiker worden bekeken of bewerkt met bestandsgebaseerde basistools. We zullen onze aandacht richten op hoe een werkgebied er op schijf uitziet en kijken naar de resourcesplugin-API.

Voorbeeldstructuur op schijf

Toen u de platform-SDK startte, is u gevraagd om een werkgebieddirectory op te geven. Dit is de directory waar verscheidene plugins interessante metagegevens opslaan die uniek zijn voor een bepaalde instance van het platform. Standaard wordt door de resourcesplugin elk project in een subdirectory van de werkgebieddirectory opgeslagen. In deze subdirectory's liggen de mappen en bestanden van de projecten.

Stel dat u de directory c:\MySDK\workspace hebt gekozen voor uw werkgebied. Binnen deze directory vinden we subdirectory's die zijn genoemd naar de projecten in het werkgebied, MyWeb en MyServlet. Deze worden de contentdirectory's van het project genoemd. Contentdirectory's worden door het platform gemaakt als de gebruiker een project maakt.

In iedere directory staan de bestanden en mappen van het project op dezelfde manier geordend als in de resourcestructuur van het werkgebied. De bestandsnamen zijn gelijk en de inhoud van de bestanden is gelijk, zowel bij toegang vanuit het bestandssysteem als vanuit het werkgebied. Het enige opvallende is het .project-bestand, waarover dadelijk meer.

   C:\MySDK\workspace  (hoofdmap van werkgebied)
      .metadata\ (directory met metagegevens van platform)
      MyWeb\ (directory van project met content voor MyWeb)
	 .project
         index.html
         images\
            logo.png
      MyServlet\ (directory van project met content voor MyServlet)
	 .project
         src\
            main.java
         bin\
            main.class

Het platform heeft de speciale directory .metadata voor interne platforminformatie. De directory .metadata van een werkgebied wordt beschouwd als een "zwarte doos". Belangrijke informatie over de structuur van het werkgebied, bijvoorbeeld de verwijzingen van het project of de eigenschappen van een resource, wordt opgeslagen in het metagegevensgedeelte van het werkgebied. De informatie is met tools alleen toegankelijk via de platform-API.  De bestanden mogen niet worden bewerkt via de generieke bestandssysteem-API.

Verder heeft ieder project zijn eigen .project-bestand, waarin de metagegevens van het project worden bewaard. Dit bestand is in wezen het schijfequivalent van de informatie in de IProjectDescription van het project.  

Met uitzondering van de directory .metadata en de .project-bestanden zijn de mappen en bestanden vrij toegankelijk voor andere tools. De bestanden en mappen kunnen worden bewerkt met niet-geïntegreerde tools, bijvoorbeeld teksteditors en hulpprogramma's voor het bestandssysteem. Het enige probleem is dat de gebruiker voorzichtig moet zijn bij het bewerken van de bestanden, zowel in de workbench als extern.  (Er is geen verschil met het bewerken van een bestand met twee onafhankelijke, zelfstandige tools.)  De workbench biedt vernieuwingsbewerkingen die de feitelijke versie in het bestandssysteem weergeven in de werkgebiedview van resources en er is een optie om het werkgebied periodiek te vernieuwen op basis van de versie van het bestandssysteem.

Voorbeeldstructuur in code

Met de resource-API kunnen we de resourcestructuur in code bewerken. We bespreken enige codefragmenten zodat u snel een indruk krijgt van de resource-API. De resource-API is gedefinieerd in een reeks interfaces in org.eclipse.core.resources. Er zijn interfaces voor alle resourcetypen, zoals IProject, IFolder en IFile. Een uitgebreid algemeen protocol is gedefinieerd in IResource. Er wordt ook gebruik gemaakt van de interface IPath uit org.eclipse.core.runtime, die gesegmenteerde paden (zoals resource- of bestandssysteempaden) bevat.

Het wijzigen van resources lijkt veel op het wijzigen van bestanden met java.io.File.  De API is gebaseerd op handles.  Als u de API gebruikt als getProject of getFolder, krijgt u als resultaat een handle naar de resource.  Er bestaan geen garanties of vereisten dat de resource zelf bestaat tot u een bewerking met de handle probeert uit te voeren. Als wilt weten of de resource bestaat, kunt u met de methode exists controleren of dit daadwerkelijk het geval is.   

Om vanuit een plugin in het werkgebied te navigeren moet u eerst IWorkspaceRoot ophalen, die de top van de resourcehiërarchie in het werkgebied bevat.

   IWorkspaceRoot myWorkspaceRoot = ResourcesPlugin.getWorkspace().getRoot();

Zodra u beschikt over een werkgebiedhoofdmap, kunt u toegang krijgen tot de projecten in het werkgebied.

   IProject myWebProject = myWorkspaceRoot.getProject("MyWeb");
   // openen indien nodig
   if (myWebProject.exists() && !myWebProject.isOpen())
      myWebProject.open(null);

Voor u een project kunt bewerken, moet u het openen. Bij het openen van een project wordt de projectstructuur van schijf gelezen en wordt deze als object in het geheugen geplaatst. Het openen van een project is een expliciete bewerking, omdat ieder open project geheugenruimte voor de projectstructuur vereist. Verder nemen open projecten soms deel aan de levenscyclus van verschillende resources (bijvoorbeeld builds), wat lang kan duren. Over het algemeen kunt u geen toegang krijgen tot gesloten projecten. Deze lijken leeg te zijn, hoewel de resources wel aanwezig zijn in het bestandssysteem.

U zult zien dat veel van deze resourcevoorbeelden de parameter null doorgeven als de resources worden bewerkt. Veel resourcebewerkingen zijn potentieel zwaar genoeg om voortgangsrapportage en gebruikersannuleringen te gebruiken. Als uw code een gebruikersinterface heeft, geeft u meestal een IProgressMonitor door, waardoor de resourcesplugin de voortgang doorgeeft als de resource wordt gewijzigd. De gebruiker kan desgewenst een bewerking annuleren.  Voorlopig wordt gewoon null doorgegeven, waardoor de voortgangsmonitor niet wordt ingeschakeld.

Als u een project hebt geopend, hebt u toegang tot de mappen en bestanden en kunt u ook nieuwe maken.  In het volgende voorbeeld wordt een bestandsresource gemaakt uit de inhoud van een bestand buiten het werkgebied.

   IFolder imagesFolder = myWebProject.getFolder("images");
   if (imagesFolder.exists()) {
      // nieuw bestand maken
      IFile newLogo = imagesFolder.getFile("newLogo.png");
      FileInputStream fileStream = new FileInputStream(
         "c:/MyOtherData/newLogo.png");
      newLogo.create(fileStream, false, null);
      // create sluit de bestandsstroom, dus geen problemen.
   }

In het bovenstaande voorbeeld maakt de eerste regel een handle voor de afbeeldingenmap. Met exists wordt gecontroleerd of de map bestaat en bewerkt kan worden. Het bestand newLogo wordt opgehaald, maar de handle vertegenwoordigt pas echt een bestand als het bestand in de laatste regel wordt gemaakt. In het voorbeeld wordt het bestand gemaakt door het te vullen met de inhoud van logo.png.

Het volgende codefragment lijkt op het vorige, maar in dit geval kopieert het het bestand newLogo uit het originele logo in plaats van het maken van een nieuw bestand op basis van de inhoud.

   IFile logo = imagesFolder.getFile("logo.png");
   if (logo.exists()) {
      IPath newLogoPath = new Path("newLogo.png");
      logo.copy(newLogoPath, false, null);
      IFile newLogo = imagesFolder.getFile("newLogo.png");
      ...
   }

Ten slotte wordt een nieuwe afbeeldingenmap gemaakt en wordt het nieuwe bestand hierin geplaatst. Het bestand wordt hernoemd als bijkomstig effect van de verplaatsing.

   ...
   IFolder newImagesFolder = myWebProject.getFolder("newimages");
   newImagesFolder.create(false, true, null);
   IPath renamedPath = newImagesFolder.getFullPath().append("renamedLogo.png");
   newLogo.move(renamedPath, false, null);
   IFile renamedLogo = newImagesFolder.getFile("renamedLogo.png");

Veel API-resourcemethoden bevatten de booleaanse vlag force, waarmee wordt aangegeven of resources die niet synchroon lopen met de corresponderende bestanden in het bestandssysteem, toch moeten worden bijgewerkt.   Zie IResource voor meer informatie. U kunt ook IResource.isSynchronized gebruiken om vast te stellen of een bepaalde resource synchroon loopt met het bestandssysteem.

Resources aan schijflocaties toewijzen

In de resourcestructuur van het voorbeeld is verondersteld dat alle directory's met projectcontent zich bevinden in de directory workspace onder de platformhoofdmap (C:\MySDK\workspace). Dit is de standaardconfiguratie voor projecten. De inhoud van een project kan echter worden toegewezen aan een willekeurige directory in een back-upsysteem, misschien zelfs op een andere computer.

Door een projectlocatie onafhankelijk van andere projecten opnieuw toe te wijzen, kan een gebruiker de inhoud van een project opslaan op een plaats die geschikt is voor het project en het projectteam. Een projectcontentdirectory moet worden beschouwd als "vrij toegankelijk". Dit betekent dat de gebruikers resources kunnen maken, bewerken en wissen via de workbench en plugins of direct met systeemtools en -editors.

Resourcepaden zijn geen volledige bestandssysteempaden. Resourcepaden zijn altijd gebaseerd op de locatie van het project (meestal de directory workspace).  Om het volledige bestandssysteempad naar een resource te krijgen, moet u de locatie zoeken met IResource.getLocationURI.  U kunt IProjectDescription.setLocation echter niet gebruiken om de locatie te wijzigen, omdat dit een eenvoudige setter voor een gegevensstructuur is.  

Als u daarentegen het corresponderende resourceobject wilt ophalen op basis van een bestandssysteempad, kunt u IWorkspaceRoot.findFilesForLocationURI of IWorkspaceRoot.findContainersForLocationURI gebruiken.

Resource-API en het bestandssysteem

Als u de resources-API gebruikt om de resourcestructuur van het werkgebied te wijzigen, worden de bestanden in het bestandssysteem gewijzigd en worden uw resourceobjecten bijgewerkt. Wat gebeurt er als resourcebestanden buiten de platform-API worden gewijzigd?

Externe resourcewijzigingen zijn in het werkgebied en resourceobjecten pas te zien als ze door de resourcesplugin worden opgemerkt. De resourcesplugin gebruikt ook een mechanisme voor het waarnemen van externe wijzigingen dat geschikt is voor ieder afzonderlijk besturingssysteem. Verder kunnen clients de resource-API gebruiken om het werkgebied en resourceobjecten rustig en zonder tussenkomst van de gebruiker te synchroniseren met het lokale bestandssysteem. De gebruiker kan ook expliciet de resourcenavigatorview van de workbench vernieuwen.

Veel methoden in de resource-API' bevatten de parameter force, waarmee wordt aangegeven hoe resources moeten worden afgehandeld als ze niet met het bestandssysteem zijn gesynchroniseerd. De API-naslag geeft per methode specifieke informatie over deze parameter. Met aanvullende methoden in de API kunt u het vernieuwen van het bestandssysteem op programmaniveau beheren, bijvoorbeeld met IResource.refreshLocal(int depth, IProgressMonitor monitor). Zie IResource voor informatie over het juiste gebruik en de kosten.

Plugins die een eigen mechanisme willen gebruiken voor het periodiek vernieuwen van het werkgebied op basis van het externe bestandssysteem, kunnen hiervoor het extensiepunt org.eclipse.core.resources.refreshProviders gebruiken. Zie Providers vernieuwen voor meer informatie.