/* ==================================================================== * * The ObjectStyle Group Software License, Version 1.0 * * Copyright (c) 2002 The ObjectStyle Group * and individual authors of the software. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. 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. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * ObjectStyle Group (http://objectstyle.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "ObjectStyle Group" and "Cayenne" * must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact andrus@objectstyle.org. * * 5. Products derived from this software may not be called "ObjectStyle" * nor may "ObjectStyle" appear in their names without prior written * permission of the ObjectStyle Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 OBJECTSTYLE GROUP OR * ITS 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. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the ObjectStyle Group. For more * information on the ObjectStyle Group, please see * <http://objectstyle.org/>. * */ package org.objectstyle.wolips.builder.internal; import java.io.File; import java.util.HashMap; import java.util.Map; import org.eclipse.core.internal.resources.ResourceException; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.objectstyle.wolips.baseforplugins.util.FileUtilities; /** * @author Harald Niesche * */ public class ResourceUtilities { /** * create a Folder recursively * * @param f * the Folder to be created * @param m * a ProgressMonitor * @throws CoreException */ public static void createFolder(IFolder f, IProgressMonitor m) throws CoreException { if (f.exists()) { return; } IContainer parent = f.getParent(); if (!f.getParent().exists()) { if (parent instanceof IFolder) { createFolder((IFolder) parent, m); } } f.create(true, true, m); } /** * check if a folder exists under a path, create it if necessary * * @param path * the path to the folder to be created (relative to the * workspace root or absolute) * @param m * a ProgressMonitor * @return true, iff the folder already existed, false, if it had to be * created * @throws CoreException */ public static boolean checkDir(IPath path, IProgressMonitor m) throws CoreException { return checkDir(path, m, false); } /** * @param path * @param m * @return * @throws CoreException */ public static boolean checkDerivedDir(IPath path, IProgressMonitor m) throws CoreException { return checkDir(path, m, true); } public static boolean checkDir(IPath path, IProgressMonitor m, boolean derived) throws CoreException { boolean result = true; IFolder f = getWorkspaceRoot().getFolder(path); if (!f.exists()) { createFolder(f, m); if (derived) { f.setDerived(true); } result = false; } return (result); } /** * checks if a path is fit to be used as destination for a copy operation if * not, the destination is prepared to be used as destination (i.e., * existing files and folders are deleted, the parent path is created, if * necessary) * * @param path * the candidate destination path * @param m * a ProgressMonitor * @return * @throws CoreException */ public static IResource checkDestination(IPath path, IProgressMonitor m, boolean deleteIfExists) throws CoreException { return checkDestination(path, m, false, deleteIfExists); } public static IResource checkDerivedDestination(IPath path, IProgressMonitor m, boolean deleteIfExists) throws CoreException { return checkDestination(path, m, true, deleteIfExists); } public static IResource checkDestination(IPath path, IProgressMonitor m, boolean derived, boolean deleteIfExists) throws CoreException { if (checkDir(path.removeLastSegments(1), m, derived)) { IResource res = getWorkspaceRoot().findMember(path); if (null != res && res.exists()) { if (deleteIfExists) { try { File f = res.getLocation().toFile(); if (f.exists()) { FileUtilities.deleteRecursively(f); } else { res.delete(true, m); } // } catch // (org.eclipse.core.internal.resources.ResourceException e) // { } catch (CoreException ce) { ce.printStackTrace(); // NOTE AK: this code was commented out, I re-instated it as // I think it's // better to have the non-deletable files in one place, // instead of messing the build directory IPath trashFolder = res.getProject().getFullPath().append("build/.trash"); IPath trashPath = trashFolder.append(res.getName() + (_getUniqifier())); checkDir(trashFolder, m); res.move(trashPath, true, null); /* * IPath newName = res.getLocation().removeLastSegments(1); * newName = newName.append(res.getName()+_getUniqifier()); * File resFile = res.getLocation().toFile(); if * (!resFile.renameTo(newName.toFile())) { throw ce; } */ } } res.refreshLocal(IResource.DEPTH_ONE, m); } return res; } return null; } private static synchronized int _getUniqifier() { return _uniqifier++; } /** * @param res * @param dest * @param m * @throws CoreException */ public static void copyDerivedOld(IResource res, IPath dest, IProgressMonitor m) throws CoreException { if (res.isTeamPrivateMember() || res.getName().equals(".svn")) return; IResource rdest = checkDestination(dest, m, true); res.copy(dest, true, null); if (null != rdest) { rdest.setDerived(true); } } /** * @param res * the Resource to copy * @param dest * where it should be copied to * @param m * ProgressMonitor to show what's going on * * @throws CoreException * if something goes wrong (and we notice) */ public static void copyDerived(IResource res, IPath dest, IProgressMonitor m) throws CoreException { if (res.isTeamPrivateMember() || res.getName().equals(".svn")) return; if (res instanceof IFolder) { IResource[] members = ((IFolder) res).members(); // MS: This is super goofy, but apparently Nonlocalized.lproj folders get fiddled with // during the build and end up going to build/Whatever.framework/Resources directly, // which makes the Resource folder get deleted, potentially tossing files you just built. boolean deleteDestination = !res.getName().equals("Nonlocalized.lproj"); IResource rdest = checkDerivedDestination(dest, m, deleteDestination); for (int i = 0; i < members.length; i++) { IResource thisOne = members[i]; if (!members[i].isTeamPrivateMember()) { IPath thisDest = dest.append(thisOne.getName()); copyDerived(thisOne, thisDest, m); } } if (null != rdest) { rdest.setDerived(true); } } else { // it's a file, let's just copy it IResource rdest = checkDestination(dest, m, true); res.copy(dest, true, m); if (null != rdest) { rdest.setDerived(true); } } } /** * @return */ public static IWorkspace getWorkspace() { return ResourcesPlugin.getWorkspace(); } /** * @return */ public static IWorkspaceRoot getWorkspaceRoot() { return ResourcesPlugin.getWorkspace().getRoot(); } protected ResourceUtilities() { super(); } private static int _uniqifier = 1; /** * @param res * @param markerId * @throws CoreException */ public static void unmarkResource(IResource res, String markerId) throws CoreException { if (res.exists()) { res.deleteMarkers(markerId, true, 0); } } /** * @param res * @param markerId * @param severity * @param message * @param location * @return * @throws CoreException */ public static IMarker markResource(IResource res, String markerId, int severity, String message, String location) throws CoreException { IMarker newMarker; if (!res.exists()) { newMarker = null; } else { try { IMarker[] marker = res.findMarkers(markerId, true, 0); if (marker.length != 1) { if (marker.length > 1) { res.deleteMarkers(markerId, false, 0); } marker = new IMarker[1]; marker[0] = res.createMarker(markerId); } if (!marker[0].exists()) { marker[0] = res.createMarker(markerId); } Map attr = new HashMap(); attr.put(IMarker.PRIORITY, Integer.valueOf(IMarker.PRIORITY_HIGH)); attr.put(IMarker.SEVERITY, Integer.valueOf(severity)); attr.put(IMarker.MESSAGE, message); attr.put(IMarker.LOCATION, location); marker[0].setAttributes(attr); newMarker = marker[0]; } catch (ResourceException e) { // MS: This happens a lot and it's not actually a problem. This is almost always a deleted file. e.printStackTrace(); newMarker = null; } } return newMarker; } }