/* * Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Business Objects nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * BasicProgramResourcePathRepository.java * Creation date: December 8, 2005. * By: Edward Lam */ package org.openquark.cal.services; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import org.openquark.cal.compiler.ModuleName; import org.openquark.cal.machine.AsynchronousFileWriter; import org.openquark.cal.machine.ProgramResourceLocator; import org.openquark.cal.machine.ProgramResourceRepository; import org.openquark.cal.runtime.MachineType; import org.openquark.util.FileChangeOutputStream; import org.openquark.util.FileSystemHelper; /** * Warning- this class should only be used by the CAL services implementation. It is not part of the * external API of the CAL platform. * <p> * A repository of program resources in the stand-alone cal workspace. * @author Edward Lam */ public class BasicProgramResourcePathRepository implements ProgramResourceRepository { /** A path mapper for program resources. */ private final ProgramResourcePathMapper pathMapper; /** The root directory for generated program resources. */ private final File sourceGenerationRoot; /** * @param sourceGenerationRoot the root directory with respect to program resource generation. * @return a provider for a program resource finder associated with the workspace. */ public static ProgramResourceRepository.Provider getResourceRepositoryProvider(final File sourceGenerationRoot) { return new ProgramResourceRepository.Provider() { public ProgramResourceRepository getRepository(MachineType machineType) { return new BasicProgramResourcePathRepository(new ProgramResourcePathMapper(machineType), sourceGenerationRoot); } }; } /** * Constructor for a BasicProgramResourcePathRepository. * * @param pathMapper * @param sourceGenerationRoot the directory which represents the root of the folder structure which containing * the program resources. This will be the parent of the module folders. */ protected BasicProgramResourcePathRepository(ProgramResourcePathMapper pathMapper, File sourceGenerationRoot) { if (sourceGenerationRoot == null || pathMapper == null) { throw new NullPointerException(); } this.pathMapper = pathMapper; this.sourceGenerationRoot = sourceGenerationRoot; } /** * {@inheritDoc} */ public InputStream getContents(ProgramResourceLocator.File fileLocator) throws IOException { File inputFile = getFile(fileLocator); if (inputFile == null) { return null; } return new FileInputStream(inputFile); } /** * {@inheritDoc} */ public void setContents(ProgramResourceLocator.File fileLocator, InputStream source) throws IOException { // Handle null source. if (source == null) { source = new ByteArrayInputStream(new byte[0]); } try { File outputFile = getFile(fileLocator); FileChangeOutputStream outputStream = null; try { // throws IOException: outputStream = new FileChangeOutputStream(outputFile); FileSystemResourceHelper.transferData(source, outputStream); } finally { try { if (outputStream != null) { outputStream.close(); } } catch (IOException ioe) { // Nothing can really be done at this point, and we don't bother reporting the error. } } // If here, an exception was not thrown. // If the file wasn't written, update the timestamp to provide a visible indication that the file data was processed. // Note: don't do this in the try block since this call would have no effect while the output stream is open. if (outputStream != null && !outputStream.isDifferent()) { getFile(fileLocator).setLastModified(System.currentTimeMillis()); } } finally { source.close(); } } /** * {@inheritDoc} */ public void ensureFolderExists(ProgramResourceLocator.Folder folder) throws IOException { File folderFile = getFile(folder); // Attempt to create the folder. if (!FileSystemHelper.ensureDirectoryExists(folderFile)) { // Check if a file already exists at the folder location. if (FileSystemHelper.fileExists(folderFile)) { throw new IOException("A file resource already exists at folder location: " + folder + "."); } throw new IOException("Folder " + folder + " could not be created. (Corresponding file system directory: '" + folderFile + "')"); } } /** * {@inheritDoc} */ public void delete(ProgramResourceLocator resourceLocator) throws IOException { Status status = new Status("Delete status."); File resourceFile = getFile(resourceLocator); if (resourceFile.exists()) { FileSystemResourceHelper.delTree(resourceFile, status); if (status.getSeverity().compareTo(Status.Severity.ERROR) >= 0) { throw new IOException(status.getDebugMessage()); } } else { // Nothing happens if the resource doesn't exist. } } /** * {@inheritDoc} */ public void delete(ProgramResourceLocator[] resourceLocators) throws IOException { Status status = new Status("Delete status."); for (final ProgramResourceLocator resourceLocator : resourceLocators) { File resourceFile = getFile(resourceLocator); if (resourceFile.exists()) { FileSystemResourceHelper.delTree(resourceFile, status); } else { // Nothing happens if the resource doesn't exist. } } if (status.getSeverity().compareTo(Status.Severity.ERROR) >= 0) { throw new IOException(status.getDebugMessage()); } } /** * {@inheritDoc} */ public boolean exists(ProgramResourceLocator resourceLocator) { if (resourceLocator instanceof ProgramResourceLocator.File) { // file return FileSystemHelper.fileExists(getFile(resourceLocator)); } else { // directory return getFile(resourceLocator).exists(); } } /** * {@inheritDoc} */ public long lastModified(ProgramResourceLocator resourceLocator) { return getFile(resourceLocator).lastModified(); } /** * {@inheritDoc} */ public ProgramResourceLocator[] getMembers(ProgramResourceLocator.Folder folder) { File folderFile = getFile(folder); File[] files = folderFile.listFiles(); if (files == null) { return null; } ProgramResourceLocator[] folderFileLocators = new ProgramResourceLocator[files.length]; for (int i = 0; i < files.length; i++) { File nthFile = files[i]; String nthFileName = nthFile.getName(); if (nthFile.isDirectory()) { folderFileLocators[i] = folder.extendFolder(nthFileName); } else { folderFileLocators[i] = folder.extendFile(nthFileName); } } return folderFileLocators; } /** * {@inheritDoc} */ public File getFile(ProgramResourceLocator resourceLocator) { ResourcePath.Folder workspaceRelativeResourceLocation = ProgramResourcePathMapper.getResourcePath(resourceLocator, pathMapper); return FileSystemResourceHelper.getResourceFile(workspaceRelativeResourceLocation, sourceGenerationRoot, false); } /** * {@inheritDoc} */ public boolean isEmpty() { File resourceRoot = FileSystemResourceHelper.getResourceFile(pathMapper.getBaseResourceFolder(), sourceGenerationRoot, false); if (!resourceRoot.exists()) { return true; } File[] files = resourceRoot.listFiles(); return (files == null || files.length == 0); } /** * {@inheritDoc} */ public long getSize(ProgramResourceLocator.File fileLocator) { File resourceRoot = getFile(fileLocator); return resourceRoot.length(); } /** * {@inheritDoc} */ public ModuleName[] getModules() { File resourceRoot = FileSystemResourceHelper.getResourceFile(pathMapper.getBaseResourceFolder(), sourceGenerationRoot, false); if (!resourceRoot.exists()) { return new ModuleName[0]; } File[] files = resourceRoot.listFiles(); ModuleName[] modules = filesToModuleNames (files); if (modules.length == 0) { // If the runtime is directly generating Java bytecode (either in static or dynamic mode) // the resource root will contain a directory for each module. However, if the runtime // is generating Java source there will be a directory "org\openquark" underneath the // resource root and this will contain a directory for each module. File sourceModuleRoot = new File(resourceRoot, "org" + File.separator + "openquark"); if (sourceModuleRoot.exists()) { files = sourceModuleRoot.listFiles(); modules = filesToModuleNames(files); } } return modules; } /** * Attemp to generate an array of ModuleName from an array of File. * @param files - array of File * @return array of ModuleName */ private ModuleName[] filesToModuleNames (File files[]) { if (files == null) { return new ModuleName[0]; } List<ModuleName> moduleNameList = new ArrayList<ModuleName>(); for (final File file : files) { String fileName = file.getName(); ModuleName moduleName = ProgramResourceLocator.createModuleNameFromPackageNameSegment(fileName); if (moduleName != null) { moduleNameList.add(moduleName); } } return moduleNameList.toArray(new ModuleName[moduleNameList.size()]); } /** * {@inheritDoc} */ public String getLocationString() { return FileSystemResourceHelper.getResourceFile(pathMapper.getBaseResourceFolder(), sourceGenerationRoot, false).getAbsolutePath(); } /** * {@inheritDoc} */ public String getDebugInfo(ProgramResourceLocator.File fileLocator) { File inputFile = getFile(fileLocator); if (inputFile == null) { return null; } else { return "from file: " + inputFile.getAbsolutePath(); } } /** * {@inheritDoc} */ public AsynchronousFileWriter getAsynchronousFileWriter() { return new BasicAsynchronousFileWriter(this); } }