Java tutorial
/* * Copyright 2015 AZYVA INC. * * This file is part of Dragom. * * Dragom is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Dragom is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Dragom. If not, see <http://www.gnu.org/licenses/>. */ package org.azyva.dragom.execcontext.plugins.impl; import java.io.File; import java.io.IOException; import java.nio.file.Path; import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Properties; import java.util.Set; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import org.apache.commons.io.FileUtils; import org.azyva.dragom.execcontext.ExecContext; import org.azyva.dragom.execcontext.ExecContextHolder; import org.azyva.dragom.execcontext.impl.DefaultExecContextFactory; import org.azyva.dragom.execcontext.plugins.WorkspaceDir; import org.azyva.dragom.execcontext.plugins.WorkspaceDirSystemModule; import org.azyva.dragom.execcontext.plugins.WorkspaceDirUserModuleVersion; import org.azyva.dragom.execcontext.plugins.WorkspacePlugin; import org.azyva.dragom.util.RuntimeExceptionUserError; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * TODO: Assumes dragom metadata dir exists, but may not be initialized based on version. * @author David Raymond * */ public class DefaultWorkspacePluginFactory { private static final Logger logger = LoggerFactory.getLogger(DefaultWorkspacePluginFactory.class); /** * File indicating that the workspace is being used. */ private static final String WORKSPACE_LOCKED_INDICATOR_FILE = ".lock"; /** * Version of the workspace data. */ private static final String WORKSPACE_VERSION_PROPERTY = "workspace-version"; /** * Version of the workspace data. */ private static final String WORKSPACE_VERSION = "1.0"; /** * WorkspacePlugin metadata file. */ private static final String WORKSPACE_METADATA_FILE = "workspace-metadata.xml"; /** * Default WorkspacePlugin implementation. * Simple workspace implementation. * * TODO: Reword. Not true anymore... * This implementation does not keep track of the modules created within the * workspace and simpl assumes the module path is a directory whose name is the * module name within the workspace directory, regardless of the version. * * In case of conflicts, which are naively assumed to not happen, unexpected * exceptions will likely be eventually be raised by the tool. */ @XmlAccessorType(XmlAccessType.NONE) @XmlRootElement(name = "workspace-default-impl") private static class WorkspaceDefaultImpl implements WorkspacePlugin { Path pathWorkspace; Path pathDragomMetadataDir; /* We really need a bidirectional map. For now, simply use two regular maps to * avoid having to use a third party library. * * We map only one bidirectional map side and use the afterUnmarshal JAXB * callback to complete the other side. * * For the actual marshalling/unmarshalling, a XmlAdapter is used so that within * the XML document the workspace directory to path information is represented as * a simple list of tuples, but within the Java class is becomes a Map. */ @XmlElement(name = "workspace-dirs", type = MapWorkspaceDirPathXmlAdapter.ListWorkspaceDirPath.class) @XmlJavaTypeAdapter(MapWorkspaceDirPathXmlAdapter.class) Map<WorkspaceDir, Path> mapWorkspaceDirPath; Map<Path, WorkspaceDir> mapPathWorkspaceDir; // Key not present means no access. 0 means write. 1+ means read with read count. Map<WorkspaceDir, Integer> mapWorkspaceDirAccessMode; // Constructor used by JAXB, when init. public WorkspaceDefaultImpl() { this.mapWorkspaceDirPath = new HashMap<WorkspaceDir, Path>(); this.mapPathWorkspaceDir = new HashMap<Path, WorkspaceDir>(); this.mapWorkspaceDirAccessMode = new HashMap<WorkspaceDir, Integer>(); } public WorkspaceDefaultImpl(Path pathWorkspace, Path pathDragomMetadataDir) { this(); this.pathWorkspace = pathWorkspace; this.pathDragomMetadataDir = pathDragomMetadataDir; this.save(); } @SuppressWarnings("unused") private void afterUnmarshal(Unmarshaller unmarshaller, Object parent) { for (Map.Entry<WorkspaceDir, Path> mapEntry : this.mapWorkspaceDirPath.entrySet()) { this.mapPathWorkspaceDir.put(mapEntry.getValue(), mapEntry.getKey()); } } @Override public void startTool() { File workspaceLockedIndicatorFile; workspaceLockedIndicatorFile = this.pathDragomMetadataDir .resolve(DefaultWorkspacePluginFactory.WORKSPACE_LOCKED_INDICATOR_FILE).toFile(); try { if (!workspaceLockedIndicatorFile.createNewFile()) { throw new RuntimeExceptionUserError( "Workspace " + this.pathWorkspace + " is currently locked."); } } catch (IOException ioe) { throw new RuntimeException(ioe); } } @Override public void endTool() { File workspaceLockedIndicatorFile; workspaceLockedIndicatorFile = this.pathDragomMetadataDir .resolve(DefaultWorkspacePluginFactory.WORKSPACE_LOCKED_INDICATOR_FILE).toFile(); workspaceLockedIndicatorFile.delete(); } private void save() { File fileWorkspaceMetadata; JAXBContext jaxbContext; Marshaller marshaller; try { fileWorkspaceMetadata = this.pathDragomMetadataDir .resolve(DefaultWorkspacePluginFactory.WORKSPACE_METADATA_FILE).toFile(); jaxbContext = JAXBContext.newInstance(WorkspaceDefaultImpl.class); marshaller = jaxbContext.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // We need to set the MapWorkspaceDirPathXmlAdapter in advance since it requires a // non-default constructor. marshaller.setAdapter(MapWorkspaceDirPathXmlAdapter.class, new MapWorkspaceDirPathXmlAdapter(this.pathWorkspace)); marshaller.marshal(this, fileWorkspaceMetadata); } catch (JAXBException je) { throw new RuntimeException(je); } } @Override public Path getPathWorkspace() { return this.pathWorkspace; } @Override public boolean isWorkspaceDirExist(WorkspaceDir workspaceDir) { return this.mapWorkspaceDirPath.containsKey(workspaceDir); } //TODO if workspace dir cannot be created for whatever reason, exception, even if it is because of conflit. //Fow now. Eventually, maybe the caller would be interested in knowing if fail because of conflict behave //gracefully in that case. But for now, make it simple. @Override public Path getWorkspaceDir(WorkspaceDir workspaceDir, EnumSet<GetWorkspaceDirModeEnum> enumSetGetWorkspaceDirModeEnum, WorkspaceDirAccessMode workspaceDirAccessMode) { Integer readCount; Path path; /* Perform basic generic validation that is common to all workspace directory * types. */ if (workspaceDirAccessMode != WorkspaceDirAccessMode.PEEK) { readCount = this.mapWorkspaceDirAccessMode.get(workspaceDir); if (readCount != null) { if (readCount == 0) { throw new RuntimeException("Workspace directory " + workspaceDir + " already accessed for writing (and new acces is " + workspaceDirAccessMode + ")."); } else if (workspaceDirAccessMode == WorkspaceDirAccessMode.READ_WRITE) { throw new RuntimeException("New access is for writing and workspace directory " + workspaceDir + " already accessed for reading (with level " + readCount + ")."); } this.mapWorkspaceDirAccessMode.put(workspaceDir, readCount + 1); } else { if (workspaceDirAccessMode == WorkspaceDirAccessMode.READ) { this.mapWorkspaceDirAccessMode.put(workspaceDir, 1); } else { this.mapWorkspaceDirAccessMode.put(workspaceDir, 0); } } } path = this.mapWorkspaceDirPath.get(workspaceDir); if ((path == null) && enumSetGetWorkspaceDirModeEnum.contains(GetWorkspaceDirModeEnum.MUST_EXIST)) { throw new RuntimeException( "WorkspacePlugin directory " + workspaceDir + " does not exist and is assumed to exist."); } if ((path != null) && enumSetGetWorkspaceDirModeEnum.contains(GetWorkspaceDirModeEnum.MUST_NOT_EXIST)) { throw new RuntimeException("WorkspacePlugin directory " + workspaceDir + " exists and mapped to " + path + " but is assumed to not exist."); } /* Get the workspace directory. */ if (workspaceDir instanceof WorkspaceDirUserModuleVersion) { path = this.getWorkspaceDirUserModuleVersion((WorkspaceDirUserModuleVersion) workspaceDir, enumSetGetWorkspaceDirModeEnum); } else if (workspaceDir instanceof WorkspaceDirSystemModule) { path = this.getWorkspaceDirSystemModule((WorkspaceDirSystemModule) workspaceDir, enumSetGetWorkspaceDirModeEnum); } else { throw new RuntimeException("Unknown WorkspaceDir class " + workspaceDir.getClass().getName() + "."); } /* Generically ensure the path is created if the caller requests it. */ if ((path != null) && !path.toFile().isDirectory() && !enumSetGetWorkspaceDirModeEnum.contains(GetWorkspaceDirModeEnum.DO_NOT_CREATE_PATH)) { if (!path.toFile().mkdir()) { throw new RuntimeException("The path " + path + " could not be created for an unknown reason."); } } return path; } private Path getWorkspaceDirUserModuleVersion(WorkspaceDirUserModuleVersion workspaceDirUserModuleVersion, EnumSet<GetWorkspaceDirModeEnum> enumSetGetWorkspaceDirModeEnum) { Path path; path = this.mapWorkspaceDirPath.get(workspaceDirUserModuleVersion); if (path == null && enumSetGetWorkspaceDirModeEnum.contains(GetWorkspaceDirModeEnum.CREATE_IF_NOT_EXIST)) { WorkspaceDir workspaceDirOther; path = this.pathWorkspace.resolve(workspaceDirUserModuleVersion.getModuleVersion() .getModuleClassificationPath().getModuleName()); workspaceDirOther = this.mapPathWorkspaceDir.get(path); if (workspaceDirOther != null) { DefaultWorkspacePluginFactory.logger.error("A workspace directory for " + workspaceDirUserModuleVersion + " is requested. The corresponding path " + path + " is already used for " + workspaceDirOther + ". This workspace implementation does not support resolving such conflicts."); return null; } DefaultWorkspacePluginFactory.logger .info("Path " + path + " is created for " + workspaceDirUserModuleVersion + "."); if (path.toFile().isDirectory()) { throw new RuntimeException("The path " + path + " for workspace directory for " + workspaceDirUserModuleVersion + " already exists but is unknown to the workspace."); } this.mapWorkspaceDirPath.put(workspaceDirUserModuleVersion, path); this.mapPathWorkspaceDir.put(path, workspaceDirUserModuleVersion); this.save(); } else if (path != null && enumSetGetWorkspaceDirModeEnum.contains(GetWorkspaceDirModeEnum.RESET_IF_EXIST)) { DefaultWorkspacePluginFactory.logger.info("Existing path " + path + " is reset (deleted and recreated empty) for " + workspaceDirUserModuleVersion + "."); try { FileUtils.deleteDirectory(path.toFile()); } catch (IOException ioe) { throw new RuntimeException("IOException raised while trying to delete the workspace directory " + path + ": " + ioe); } } return path; } private Path getWorkspaceDirSystemModule(WorkspaceDirSystemModule workspaceDirSystemModule, EnumSet<GetWorkspaceDirModeEnum> enumSetGetWorkspaceDirModeEnum) { Path path; path = this.mapWorkspaceDirPath.get(workspaceDirSystemModule); if (path == null && enumSetGetWorkspaceDirModeEnum.contains(GetWorkspaceDirModeEnum.CREATE_IF_NOT_EXIST)) { WorkspaceDir workspaceDirOther; path = this.pathDragomMetadataDir .resolve(workspaceDirSystemModule.getModuleClassificationPath().getModuleName()); workspaceDirOther = this.mapPathWorkspaceDir.get(path); if (workspaceDirOther != null) { throw new RuntimeException("A workspace directory for " + workspaceDirSystemModule + " is requested. The corresponding path " + path + " is already used for " + workspaceDirOther + ". This workspace implementation does not support resolving such conflicts."); } DefaultWorkspacePluginFactory.logger .info("Path " + path + " is created for " + workspaceDirSystemModule + "."); if (path.toFile().isDirectory()) { throw new RuntimeException("The path " + path + " for workspace directory for " + workspaceDirSystemModule + " already exists but is unknown to the workspace."); } this.mapWorkspaceDirPath.put(workspaceDirSystemModule, path); this.mapPathWorkspaceDir.put(path, workspaceDirSystemModule); this.save(); } else if (path != null && enumSetGetWorkspaceDirModeEnum.contains(GetWorkspaceDirModeEnum.RESET_IF_EXIST)) { DefaultWorkspacePluginFactory.logger.info("Existing path " + path + " is reset (deleted and recreated empty) for " + workspaceDirSystemModule + "."); try { FileUtils.deleteDirectory(path.toFile()); } catch (IOException ioe) { throw new RuntimeException("IOException raised while trying to delete the workspace directory " + path + ": " + ioe); } } return path; } @Override public void releaseWorkspaceDir(Path pathWorkspaceDir) { WorkspaceDir workspaceDir; Integer readCount; workspaceDir = this.mapPathWorkspaceDir.get(pathWorkspaceDir); if (workspaceDir == null) { throw new RuntimeException( "The path " + pathWorkspaceDir + " does not correspond to a workspace directory."); } readCount = this.mapWorkspaceDirAccessMode.get(workspaceDir); if (readCount == null) { throw new RuntimeException("Workspace directory " + workspaceDir + " is not accessed."); } if ((readCount == 0) || (readCount == 1)) { this.mapWorkspaceDirAccessMode.remove(workspaceDir); } else { this.mapWorkspaceDirAccessMode.put(workspaceDir, readCount - 1); } } @Override public void updateWorkspaceDir(WorkspaceDir workspaceDir, WorkspaceDir workspaceDirNew) { Integer readCount; Path path; readCount = this.mapWorkspaceDirAccessMode.get(workspaceDir); if ((readCount == null) || (readCount != 0)) { throw new RuntimeException( "Workspace directory " + workspaceDir + " must be accessed for writing to update it."); } path = this.mapWorkspaceDirPath.get(workspaceDir); if (path == null) { throw new RuntimeException("No entry exists for workspace directory " + workspaceDir + "."); } if (workspaceDir instanceof WorkspaceDirUserModuleVersion) { if (!(workspaceDirNew instanceof WorkspaceDirUserModuleVersion)) { throw new RuntimeException("New workspace directory " + workspaceDir + " must be of the same type as original one " + workspaceDirNew + "."); } if (!((WorkspaceDirUserModuleVersion) workspaceDir).getModuleVersion().getModuleClassificationPath() .equals(((WorkspaceDirUserModuleVersion) workspaceDirNew).getModuleVersion() .getModuleClassificationPath())) { throw new RuntimeException("New workspace directory " + workspaceDirNew + " must refer to the same module classification path as original workspace directory " + workspaceDir + "."); } } else if (workspaceDir instanceof WorkspaceDirSystemModule) { if (!(workspaceDirNew instanceof WorkspaceDirSystemModule)) { throw new RuntimeException("New workspace directory " + workspaceDir + " must be of the same type as original one " + workspaceDirNew + "."); } if (!((WorkspaceDirSystemModule) workspaceDir).getModuleClassificationPath() .equals(((WorkspaceDirSystemModule) workspaceDirNew).getModuleClassificationPath())) { throw new RuntimeException("New workspace directory " + workspaceDirNew + " must refer to the same module classification path as original workspace directory " + workspaceDir + "."); } } else { throw new RuntimeException("Invalid workspace directory type " + workspaceDir + "."); } if (this.mapWorkspaceDirPath.get(workspaceDirNew) != null) { throw new RuntimeException("New workspace directory " + workspaceDirNew + " must not exist."); } this.mapWorkspaceDirPath.remove(workspaceDir); this.mapWorkspaceDirPath.put(workspaceDirNew, path); this.mapPathWorkspaceDir.put(path, workspaceDirNew); this.mapWorkspaceDirAccessMode.remove(workspaceDir); this.mapWorkspaceDirAccessMode.put(workspaceDirNew, 0); this.save(); } @Override public void deleteWorkspaceDir(WorkspaceDir workspaceDir) { Integer readCount; Path path; readCount = this.mapWorkspaceDirAccessMode.get(workspaceDir); if ((readCount == null) || (readCount != 0)) { throw new RuntimeException( "Workspace directory " + workspaceDir + " must be accessed for writing to delete it."); } path = this.mapWorkspaceDirPath.get(workspaceDir); if (path != null) { try { FileUtils.deleteDirectory(path.toFile()); } catch (IOException ioe) { throw new RuntimeException("IOException raised while trying to delete the workspace directory " + path + ": " + ioe); } this.mapWorkspaceDirPath.remove(workspaceDir); this.mapPathWorkspaceDir.remove(path); this.save(); } } @Override public Set<WorkspaceDir> getSetWorkspaceDir(Class<? extends WorkspaceDir> workspaceDirClass) { Set<WorkspaceDir> setWorkspaceDir; setWorkspaceDir = new HashSet<WorkspaceDir>(this.mapWorkspaceDirPath.keySet()); if (workspaceDirClass != null) { Iterator<WorkspaceDir> iteratorWorkspaceDir; iteratorWorkspaceDir = setWorkspaceDir.iterator(); while (iteratorWorkspaceDir.hasNext()) { WorkspaceDir workspaceDir; workspaceDir = iteratorWorkspaceDir.next(); if (workspaceDir.getClass() != workspaceDirClass) { iteratorWorkspaceDir.remove(); } } } return setWorkspaceDir; } @Override public Set<WorkspaceDir> getSetWorkspaceDir(WorkspaceDir workspaceDirIncomplete) { Set<WorkspaceDir> setWorkspaceDir; setWorkspaceDir = new HashSet<WorkspaceDir>(this.mapWorkspaceDirPath.keySet()); if (workspaceDirIncomplete != null) { Iterator<WorkspaceDir> iteratorWorkspaceDir; iteratorWorkspaceDir = setWorkspaceDir.iterator(); while (iteratorWorkspaceDir.hasNext()) { WorkspaceDir workspaceDir; workspaceDir = iteratorWorkspaceDir.next(); if (workspaceDir.getClass() != workspaceDirIncomplete.getClass()) { iteratorWorkspaceDir.remove(); } else if (workspaceDirIncomplete instanceof WorkspaceDirUserModuleVersion) { WorkspaceDirUserModuleVersion workspaceDirUserModuleVersion; WorkspaceDirUserModuleVersion workspaceDirUserModuleVersionIncomplete; workspaceDirUserModuleVersion = (WorkspaceDirUserModuleVersion) workspaceDir; workspaceDirUserModuleVersionIncomplete = (WorkspaceDirUserModuleVersion) workspaceDirIncomplete; if ((workspaceDirUserModuleVersionIncomplete.getModuleVersion() .getModuleClassificationPath() != null) && !workspaceDirUserModuleVersionIncomplete.getModuleVersion() .getModuleClassificationPath().equals(workspaceDirUserModuleVersion .getModuleVersion().getModuleClassificationPath())) { iteratorWorkspaceDir.remove(); } else if ((workspaceDirUserModuleVersionIncomplete.getModuleVersion().getVersion() != null) && !workspaceDirUserModuleVersionIncomplete.getModuleVersion().getVersion() .equals(workspaceDirUserModuleVersion.getModuleVersion().getVersion())) { iteratorWorkspaceDir.remove(); } } else if (workspaceDirIncomplete instanceof WorkspaceDirSystemModule) { WorkspaceDirSystemModule workspaceDirSystemModule; WorkspaceDirSystemModule workspaceDirSystemModuleIncomplete; workspaceDirSystemModule = (WorkspaceDirSystemModule) workspaceDir; workspaceDirSystemModuleIncomplete = (WorkspaceDirSystemModule) workspaceDirIncomplete; if ((workspaceDirSystemModuleIncomplete.getModuleClassificationPath() != null) && !workspaceDirSystemModuleIncomplete.getModuleClassificationPath() .equals(workspaceDirSystemModule.getModuleClassificationPath())) { iteratorWorkspaceDir.remove(); } } } } return setWorkspaceDir; } @Override public boolean isPathWorkspaceDirExists(Path pathWorkspaceDir) { return this.mapPathWorkspaceDir.containsKey(pathWorkspaceDir); } @Override public WorkspaceDir getWorkspaceDirFromPath(Path pathWorkspaceDir) { if (!this.mapPathWorkspaceDir.containsKey(pathWorkspaceDir)) { throw new RuntimeException( "No workspace directory corresponds to the path " + pathWorkspaceDir + "."); } return this.mapPathWorkspaceDir.get(pathWorkspaceDir); } } /** * TODO: Review * Create the WorkspacePlugin using the following strategy: * * - For the WorkspacePlugin, the workspace directory is considered. If the system * property org.azyva.dragom.WorkspaceDir is defined, the path specified is * taken as the workspace. Otherwise the current working directory is used. * - If the system property org.azyva.dragom.WorkspaceFactory is defined, the * static method getWorkspaceInstance of the specified class is called to obtain * the WorkspacePlugin instance to set in ExecContext. * - Otherwise if the workspace directory contains the * .dragom/workspace-init.properties file, the class identified by the * workspace.factory property is used as the factory. * - Otherwise (if the workspace directory does not contain the * .dragom/workspace-init.properties file), if the system property * org.azyva.dragom.DefaultWorkspaceFactory is defined, the specified class is * used as the factory. * - Otherwise, DefaultWorkspaceFactory is used as the factory. * - In all cases once a WorkspacePlugin instance is obtained, it is initialized by * calling either init or load depending on whether the workspace directory * contained the .dragom/workspace-init.properties file. * * @return See description. */ public static WorkspacePlugin getInstance(Properties propertiesInit) { ExecContext execContext; String workspaceVersion; boolean indWorkspaceInit; Path pathWorkspace; Path pathDragomMetadataDir; WorkspaceDefaultImpl workspaceDefaultImpl; execContext = ExecContextHolder.get(); workspaceVersion = execContext.getProperty(DefaultWorkspacePluginFactory.WORKSPACE_VERSION_PROPERTY); // We infer the fact that the workspace is initialized or not based on the // presence of the workspace-version property. We do not take into consideration // whether the workspace is empty or not. This allows for example initializing a // Dragom workspace within an Eclipse workspace. if (workspaceVersion == null) { execContext.setProperty(DefaultWorkspacePluginFactory.WORKSPACE_VERSION_PROPERTY, DefaultWorkspacePluginFactory.WORKSPACE_VERSION); indWorkspaceInit = false; } else { if (!workspaceVersion.equals(DefaultWorkspacePluginFactory.WORKSPACE_VERSION)) { throw new RuntimeException("Unsupported workspace version " + workspaceVersion + ". Only version " + DefaultWorkspacePluginFactory.WORKSPACE_VERSION + " is supported by this WorkspacePlugin factory."); } indWorkspaceInit = true; } pathWorkspace = DefaultExecContextFactory.getPathWorkspace(propertiesInit); pathDragomMetadataDir = pathWorkspace.resolve(DefaultExecContextFactory.DRAGOM_METADATA_DIR); if (indWorkspaceInit) { File fileWorkspaceMetadata; JAXBContext jaxbContext; Unmarshaller unmarshaller; try { fileWorkspaceMetadata = pathDragomMetadataDir .resolve(DefaultWorkspacePluginFactory.WORKSPACE_METADATA_FILE).toFile(); jaxbContext = JAXBContext.newInstance(WorkspaceDefaultImpl.class); unmarshaller = jaxbContext.createUnmarshaller(); // We need to set the MapWorkspaceDirPathXmlAdapter in advance since it requires a // non-default constructor. unmarshaller.setAdapter(MapWorkspaceDirPathXmlAdapter.class, new MapWorkspaceDirPathXmlAdapter(pathWorkspace)); workspaceDefaultImpl = (WorkspaceDefaultImpl) unmarshaller.unmarshal(fileWorkspaceMetadata); } catch (JAXBException e) { throw new RuntimeException(e); } workspaceDefaultImpl.pathWorkspace = pathWorkspace; workspaceDefaultImpl.pathDragomMetadataDir = pathDragomMetadataDir; } else { workspaceDefaultImpl = new WorkspaceDefaultImpl(pathWorkspace, pathDragomMetadataDir); } return workspaceDefaultImpl; } }