/*
 * Copyright 2010 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.guvnor.tools.utils.webdav;

import java.io.InputStream;
import java.net.URL;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.webdav.IContext;
import org.eclipse.webdav.ILocator;
import org.eclipse.webdav.IResponse;
import org.eclipse.webdav.client.RemoteDAVClient;
import org.eclipse.webdav.client.WebDAVFactory;
import org.eclipse.webdav.http.client.HttpClient;
import org.eclipse.webdav.http.client.IAuthenticator;
import org.guvnor.tools.Activator;

/**
 * WebDav wrapper client.
 */
public class WebDavClient implements IWebDavClient {

    private RemoteDAVClient client;

    private WebDavAuthenticator platformAuthenticator;

    /**
     * Ctor for this wrapper WebDav client.
     * @param serverUrl The WebDav repository location (server)
     */
    /** package */ WebDavClient(URL serverUrl) {
        HttpClient httpClient = null;
        if (Activator.getDefault().useDebugHttpClient()) {
            httpClient = new DebugHttpClient();
        } else {
            httpClient = new HttpClient();
        }
        platformAuthenticator =  new WebDavAuthenticator(serverUrl);
        httpClient.setAuthenticator(platformAuthenticator);
        client = new RemoteDAVClient(new WebDAVFactory(), httpClient);
    }

    /*
     * (non-Javadoc)
     * @see org.guvnor.tools.utils.webdav.IWebDavClient#setSessionAuthenticator(org.eclipse.webdav.http.client.IAuthenticator)
     */
    public void setSessionAuthenticator(IAuthenticator sessionAuthen) {
        if (sessionAuthen != null) {
            client.getHttpClient().setAuthenticator(sessionAuthen);
        } else {
            client.getHttpClient().setAuthenticator(platformAuthenticator);
        }
    }

    /*
     * (non-Javadoc)
     * @see org.guvnor.tools.utils.webdav.IWebDavClient#getClient()
     */
    public RemoteDAVClient getClient() {
        return client;
    }

    /*
     * (non-Javadoc)
     * @see org.guvnor.tools.utils.webdav.IWebDavClient#createContext()
     */
    public IContext createContext() {
        IContext context = WebDAVFactory.contextFactory.newContext();
        // Need to make sure the USER-AGENT header is present for Guvnor
        context.put("USER-AGENT", "guvnor"); //$NON-NLS-1$ //$NON-NLS-2$
        return context;
    }

    /*
     * (non-Javadoc)
     * @see org.guvnor.tools.utils.webdav.IWebDavClient#listDirectory(java.lang.String)
     */
    public Map<String, ResourceProperties> listDirectory(String path) throws Exception {
        IResponse response = null;
        try {
            IContext context = createContext();
            context.put("Depth", "1"); //$NON-NLS-1$ //$NON-NLS-2$
            ILocator locator = WebDAVFactory.locatorFactory.newLocator(path);
            response = client.propfind(locator, context, null);
            if (response.getStatusCode() != IResponse.SC_MULTI_STATUS) {
                throw new WebDavException(response);
            }
            Map<String, ResourceProperties> res =
                StreamProcessingUtils.parseListing(path, response.getInputStream());
            addGuvnorResourceProperties(res, path);
            return res;
        } finally {
            if (response != null) {
                response.close();
            }
        }
    }

    private void addGuvnorResourceProperties(Map<String,
                                            ResourceProperties> props,
                                            String path) throws Exception {
        IResponse response = null;
        try {
            String apiVer = changeToAPICall(path);
            Properties guvProps = new Properties();
            response = getResourceInputStream(apiVer);
            guvProps.load(response.getInputStream());
            response.getInputStream();
            for (Iterator<String> it = props.keySet().iterator(); it.hasNext();) {
                String oneKey = it.next();
                String val = guvProps.getProperty(oneKey);
                if (val != null) {
                    ResourceProperties resProps = props.get(oneKey);
                    StringTokenizer tokens = new StringTokenizer(val, ","); //$NON-NLS-1$
//                    String dateStamp = tokens.nextToken();
//                    String revision = tokens.nextToken();
                    if(tokens.hasMoreElements()){
                        resProps.setLastModifiedDate(tokens.nextToken());
                    }
                    if(tokens.hasMoreElements()){
                        resProps.setRevision(tokens.nextToken());
                    }
                }
            }
        } finally {
            if (response != null) {
                response.close();
            }
        }
    }

    /*
     * (non-Javadoc)
     * @see org.guvnor.tools.utils.webdav.IWebDavClient#queryProperties(java.lang.String)
     */
    public ResourceProperties queryProperties(String resource) throws Exception {
        IResponse response = null;
        try {
            IContext context = createContext();
            context.put("Depth", "1"); //$NON-NLS-1$ //$NON-NLS-2$
            ILocator locator = WebDAVFactory.locatorFactory.newLocator(resource);
            response = client.propfind(locator, context, null);
            if (response.getStatusCode() != IResponse.SC_MULTI_STATUS
               && response.getStatusCode() != IResponse.SC_OK) {
                throw new WebDavException(response);
            }
            Map<String, ResourceProperties> props =
                StreamProcessingUtils.parseListing("", response.getInputStream()); //$NON-NLS-1$
            if (props.keySet().size() != 1) {
                throw new Exception(props.keySet().size() + " entries found for " + resource); //$NON-NLS-1$
            }
            String fullpath = props.keySet().iterator().next();
            ResourceProperties res = props.get(fullpath);
            String filename = new Path(fullpath).lastSegment();
            addGuvnorResourceProperties(res, filename, resource);
            return res;
        } finally {
            if (response != null) {
                response.close();
            }
        }
    }

    /**
     * Adds Guvnor-specific resource properties to the collection.
     * @param props The resource properties colleciton
     * @param filename The name of the resource
     * @param resource The full path to the resource in Guvnor
     * @throws Exception
     */
    private void addGuvnorResourceProperties(ResourceProperties props,
                                            String filename, String resource) throws Exception {
        if (props == null) {
            return;
        }
        IResponse response = null;
        try {
            String path = resource.substring(0, resource.lastIndexOf('/'));
            String apiVer = changeToAPICall(path);
            Properties guvProps = new Properties();
            response = getResourceInputStream(apiVer);
            guvProps.load(response.getInputStream());
            String val = guvProps.getProperty(filename);
            if (val != null) {
                StringTokenizer tokens = new StringTokenizer(val, ","); //$NON-NLS-1$
//                String dateStamp = tokens.nextToken();
//                String revision = tokens.nextToken();
                if(tokens.hasMoreElements()){
                    props.setLastModifiedDate(tokens.nextToken());
                }
                if(tokens.hasMoreElements()){
                    props.setRevision(tokens.nextToken());
                }
            } else {
                Exception nfe = new Exception("Failed to get Guvnor properties for " + filename); //$NON-NLS-1$
                Activator.getDefault().writeLog(IStatus.WARNING, nfe.getMessage(), nfe);
            }
        } finally {
            if (response != null) {
                response.close();
            }
        }
    }

    /*
     * (non-Javadoc)
     * @see org.guvnor.tools.utils.webdav.IWebDavClient#getResourceContents(java.lang.String)
     */
    public String getResourceContents(String resource) throws Exception {
        IResponse response = null;
        try {
            response = getResourceInputStream(resource);
            return StreamProcessingUtils.getStreamContents(response.getInputStream());
        } finally {
            if (response != null) {
                response.close();
            }
        }
    }

    /*
     * (non-Javadoc)
     * @see org.guvnor.tools.utils.webdav.IWebDavClient#getResourceVersionContents(java.lang.String, java.lang.String)
     */
    public String getResourceVersionContents(String resource, String version) throws Exception {
        String apiVer = changeToAPICall(resource) + "?version=" + version; //$NON-NLS-1$
        return getResourceContents(apiVer);
    }

    /*
     * (non-Javadoc)
     * @see org.guvnor.tools.utils.webdav.IWebDavClient#getInputStream(java.lang.String)
     */
    public IResponse getResourceInputStream(String resource) throws Exception {
        ILocator locator = WebDAVFactory.locatorFactory.newLocator(resource);
        IResponse response = client.get(locator, createContext());
        if (response.getStatusCode() != IResponse.SC_OK) {
            throw new WebDavException(response);
        }
        return response;
    }

    /*
     * (non-Javadoc)
     * @see org.guvnor.tools.utils.webdav.IWebDavClient#getResourceVersionInputStream(java.lang.String, java.lang.String)
     */
    public IResponse getResourceVersionInputStream(String resource, String version) throws Exception {
        String apiVer = changeToAPICall(resource) + "?version=" + version; //$NON-NLS-1$
        return getResourceInputStream(apiVer);
    }

    /*
     * (non-Javadoc)
     * @see org.guvnor.tools.utils.webdav.IWebDavClient#createResource(java.lang.String, java.io.InputStream)
     */
    public boolean createResource(String resource, InputStream is) throws Exception {
        return createResource(resource, is, true);
    }

    /*
     * (non-Javadoc)
     * @see org.guvnor.tools.utils.webdav.IWebDavClient#createResource(java.lang.String, java.io.InputStream, boolean)
     */
    public boolean createResource(String resource, InputStream is, boolean overwrite) throws Exception {
        boolean res = true;
        if (!overwrite) {
            try {
                if (queryProperties(resource) != null) {
                    res = false;
                }
            } catch (WebDavException e) {
                if (e.getErrorCode() != IResponse.SC_NOT_FOUND) {
                    throw e;
                }
            }
        }
        IResponse response = null;
        try {
            if (res) {
                ILocator locator = WebDAVFactory.locatorFactory.newLocator(resource);
                response = client.put(locator, createContext(), is);
                if (response.getStatusCode() != IResponse.SC_OK
                   && response.getStatusCode() != IResponse.SC_CREATED) {
                    throw new WebDavException(response);
                }
            }
        } finally {
            if (response != null) {
                response.close();
            }
        }
        return res;
    }

    /*
     * (non-Javadoc)
     * @see org.guvnor.tools.utils.webdav.IWebDavClient#putResource(java.lang.String, java.io.InputStream)
     */
    public void putResource(String resource, InputStream is) throws Exception {
        IResponse response = null;
        try {
            ILocator locator = WebDAVFactory.locatorFactory.newLocator(resource);
            response = client.put(locator, createContext(), is);
            if (response.getStatusCode() != IResponse.SC_OK
               && response.getStatusCode() != IResponse.SC_NO_CONTENT
               && response.getStatusCode() != IResponse.SC_CREATED) {
                throw new WebDavException(response);
            }
        } finally {
            if (response != null) {
                response.close();
            }
        }
    }

    /*
     * (non-Javadoc)
     * @see org.guvnor.tools.utils.webdav.IWebDavClient#getResourceVersions(java.lang.String)
     */
    public IResponse getResourceVersions(String resource) throws Exception {
        String apiVer = changeToAPICall(resource) + "?version=all"; //$NON-NLS-1$
        return getResourceInputStream(apiVer);
    }

    /*
     * (non-Javadoc)
     * @see org.guvnor.tools.utils.webdav.IWebDavClient#deleteResource(java.lang.String)
     */
    public void deleteResource(String resource) throws Exception {
        IResponse response = null;
        try {
            ILocator locator = WebDAVFactory.locatorFactory.newLocator(resource);
            response = client.delete(locator, createContext());
            if (response.getStatusCode() != IResponse.SC_NO_CONTENT
               && response.getStatusCode() != IResponse.SC_OK) {
                throw new WebDavException(response);
            }
        } finally {
            if (response != null) {
                response.close();
            }
        }
    }

    /**
     * Converts the WedDav resource path to a Guvnor "API path."
     */
    private String changeToAPICall(String path) {
        return path.replaceFirst("/webdav/", "/api/"); //$NON-NLS-1$ //$NON-NLS-2$
    }
}


/*
 * Copyright 2010 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.guvnor.tools.actions;

import java.net.URL;
import java.text.MessageFormat;
import java.util.Iterator;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.IObjectActionDelegate;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.webdav.IResponse;
import org.guvnor.tools.Activator;
import org.guvnor.tools.Messages;
import org.guvnor.tools.utils.ActionUtils;
import org.guvnor.tools.utils.GuvnorMetadataProps;
import org.guvnor.tools.utils.GuvnorMetadataUtils;
import org.guvnor.tools.utils.PlatformUtils;
import org.guvnor.tools.utils.webdav.IWebDavClient;
import org.guvnor.tools.utils.webdav.WebDavClientFactory;
import org.guvnor.tools.utils.webdav.WebDavException;
import org.guvnor.tools.utils.webdav.WebDavServerCache;

/**
 * Deletes a resource in Guvnor.
 */
public class DeleteAction implements IObjectActionDelegate {

    private IStructuredSelection selectedItems;

    private IWorkbenchPart targetPart;

    public DeleteAction() {
        super();
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.IObjectActionDelegate#setActivePart(org.eclipse.jface.action.IAction, org.eclipse.ui.IWorkbenchPart)
     */
    public void setActivePart(IAction action, IWorkbenchPart targetPart) {
        this.targetPart = targetPart;
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
     */
    @SuppressWarnings("unchecked")
    public void run(IAction action) {
        if (selectedItems == null) {
            return;
        }
        String msg = null;
        if (selectedItems.size() == 1) {
            msg = MessageFormat.format(Messages.getString("delete.singlefile.confirmation"), //$NON-NLS-1$
                                      new Object[] { ((IFile)selectedItems.getFirstElement()).getName() });
        } else {
            msg = MessageFormat.format(Messages.getString("delete.multifile.confirmation"), //$NON-NLS-1$
                                      new Object[] { String.valueOf(selectedItems.size()) });
        }
        if (!MessageDialog.openConfirm(targetPart.getSite().getShell(),
                                      Messages.getString("delete.confirmation.dialog.caption"), msg)) { //$NON-NLS-1$
            return;
        }
        for (Iterator it = selectedItems.iterator(); it.hasNext();) {
            Object oneItem = it.next();
            if (oneItem instanceof IFile) {
                processDelete((IFile)oneItem);
            }
        }
        DisconnectAction dsAction = new DisconnectAction();
        dsAction.disconnect(selectedItems);
        PlatformUtils.updateDecoration();
        PlatformUtils.refreshRepositoryView();
    }

    private void processDelete(IFile selectedFile) {
        try {
            GuvnorMetadataProps props = GuvnorMetadataUtils.getGuvnorMetadata(selectedFile);
            assert(props != null);
            IWebDavClient client = WebDavServerCache.getWebDavClient(props.getRepository());
            if (client == null) {
                client = WebDavClientFactory.createClient(new URL(props.getRepository()));
                WebDavServerCache.cacheWebDavClient(props.getRepository(), client);
            }
            try {
                client.deleteResource(props.getFullpath());
            } catch (WebDavException wde) {
                if (wde.getErrorCode() != IResponse.SC_UNAUTHORIZED) {
                    // If not an authentication failure, we don't know what to do with it
                    throw wde;
                }
                boolean retry = PlatformUtils.getInstance().
                                    authenticateForServer(props.getRepository(), client);
                if (retry) {
                    client.deleteResource(props.getFullpath());
                }
            }

        } catch (Exception e) {
            Activator.getDefault().displayError(IStatus.ERROR, e.getMessage(), e, true);
        }
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction, org.eclipse.jface.viewers.ISelection)
     */
    public void selectionChanged(IAction action, ISelection selection) {
        boolean validResourceSet = ActionUtils.checkResourceSet(selection, true);
        if (validResourceSet) {
            action.setEnabled(true);
            selectedItems = (IStructuredSelection)selection;
        } else {
            action.setEnabled(false);
            selectedItems = null;
        }
    }
}


/*
 * Copyright 2015 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

package org.eclipse.webdav.client;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import org.eclipse.webdav.*;
import org.eclipse.webdav.dom.ElementEditor;
import org.eclipse.webdav.dom.MalformedElementException;
import org.eclipse.webdav.internal.kernel.*;
import org.eclipse.webdav.internal.kernel.utils.Assert;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
 * The CollectionHandle class represents a resource on the
 * WebDAV server that supports collection semantics.
 *

 * Note: This class/interface is part of an interim API that is still under
 * development and expected to change significantly before reaching stability.
 * It is being made available at this early stage to solicit feedback from pioneering
 * adopters on the understanding that any code that uses this API will almost
 * certainly be broken (repeatedly) as the API evolves.
 *

 */
public class CollectionHandle extends AbstractResourceHandle {

    /**
     * Creates a new CollectionHandle from the given
     * DAVClient and Locator.
     *

     * A CollectionHandle is a resource handle for DAV resources
     * with internal members.

     *
     * @param davClient the client used to access the WebDAV server.
     * @param locator the reference to the collection resource on the
     * server.
     */
    public CollectionHandle(DAVClient davClient, ILocator locator) {
        super(davClient, locator);
    }

    /**
     * Bring the receiver under baseline control.
     *
     * @throws DAVException if the baseline control operation failed.
     * @see IServer#baselineControl(Locator, Context, Document)
     */
    public void baselineControl() throws DAVException {
        IResponse response = null;
        try {
            response = davClient.baselineControl(locator, newContext(), null);
            examineResponse(response);
        } catch (IOException e) {
            throw new SystemException(e);
        } finally {
            closeResponse(response);
        }
    }

    /**
     * Create a new version-controlled configuration on the given baseline.
     *
     * @throws DAVException if the baseline control operation failed.
     * @see IServer#baselineControl(Locator, Context, Document)
     */
    public void baselineControl(ILocator baseline) throws DAVException {
        Assert.isNotNull(baseline);

        // Build the document body to describe the baseline control element.
        Document document = newDocument();
        Element root = ElementEditor.create(document, "baseline-control"); //$NON-NLS-1$
        ElementEditor.addChild(root, "baseline", //$NON-NLS-1$
                baseline.getResourceURL(), new String[] {"baseline"}, //$NON-NLS-1$
                true);

        // Send the baseline control method to the server and check the response.
        IResponse response = null;
        try {
            response = davClient.baselineControl(locator, newContext(), document);
            examineResponse(response);
        } catch (IOException e) {
            throw new SystemException(e);
        } finally {
            closeResponse(response);
        }
    }

    /**
     * Binds the given member in this collection to the resource identified
     * by the given source locator. If the member already exists, or is
     * already bound to a resource, it is not replaced.
     *
     * @param member a member in this collection
     * @param source the location of a resource
     * @throws DAVException if the binding could not be created
     * @see #bind(String, Locator, boolean)
     * @see IServer#bind(Locator, Locator, Context)
     */
    public void bind(String member, ILocator source) throws DAVException {
        bind(member, source, false);
    }

    /**
     * Binds the given member in this collection to the resource identified
     * by the given source locator. If overwrite is false and
     * such a member already exists, or such a member is already bound to a
     * resource, it is not replaced. Otherwise, if overwrite is
     * true and such a member already exists, or such a member
     * is already bound to a resource, it is replaced.
     *
     * @param member    a member in this collection
     * @param source    the location of a resource
     * @param overwrite a boolean indicating whether or not any existing
     *                  resource or binding is replaced
     * @throws DAVException if the binding could not be created
     * @see #bind(String, Locator, boolean)
     * @see IServer#bind(Locator, Locator, Context)
     */
    public void bind(String member, ILocator source, boolean overwrite) throws DAVException {
        IContext context = newContext();
        context.setOverwrite(overwrite);
        ILocator destination = getMember(member);

        IResponse response = null;
        try {
            response = davClient.bind(source, destination, context);
            examineResponse(response);
        } catch (IOException e) {
            throw new SystemException(e);
        } finally {
            closeResponse(response);
        }
    }

    /**
     * Check out this resource. Returns a resource handle on the checked out
     * version selector, or the working resource if a version is checked out.
     *

     * Note that a checked-out version-controlled collection has members that are
     * themselves version-controlled resources, or unversioned resources; however,
     * working collection members are always version history resources.

     *
     * @return the checked out resource as a CollectionHandle.
     * @throws DAVException if there is a problem checking out the receiver.
     */
    public AbstractResourceHandle checkOut() throws DAVException {
        ILocator locator = protectedCheckOut();
        return new CollectionHandle(davClient, locator);
    }

    /**
     * Create this collection in the repository.
     *

     * This corresponds to a WebDAV MKCOL method.

     *
     * @exception DAVException if there was a problem creating this collection
     * @see IServer#mkcol(ILocator, IContext, IElement)
     */
    public void create() throws DAVException {
        IResponse response = null;
        try {
            response = davClient.mkcol(locator, newContext(), null);
            examineResponse(response);
        } catch (IOException e) {
            throw new SystemException(e);
        } finally {
            closeResponse(response);
        }
    }

    /**
     * Create the receiver and any parent collections that must be created
     * on the path to the receiver.
     *
     * @throws DAVException if there is a problem creating the collections.
     */
    public void mkdirs() throws DAVException {
        mkdirs(this);
    }

    protected void mkdirs(CollectionHandle handle) throws DAVException {
        IResponse response = null;
        try {
            // Attempt to create the collection.
            response = davClient.mkcol(handle.locator, newContext(), null);

            int status = response.getStatusCode();
            if (status == IResponse.SC_METHOD_NOT_ALLOWED) {
                // A resource already exists at this location.
                // Check that it is a collection resource (otherwise fall through to examine response)
                if (handle.isCollection())
                    return;
            }

            if (status == IResponse.SC_FORBIDDEN) {
                // if this is a collection and exists return
                if (handle.isCollection() && handle.exists())
                    return;
            }

            if (status == IResponse.SC_CONFLICT) {
                // close the response and try to create the parents
                closeResponse(response);
                // Intermediate collections are missing.
                CollectionHandle parent = handle.getParent();
                mkdirs(parent);
                // re-attempt to create the folder after the parents have been created
                response = davClient.mkcol(handle.locator, newContext(), null);
            }
            // We got some other response code, so check for failures.
            examineResponse(response);
        } catch (IOException e) {
            throw new SystemException(e);
        } finally {
            closeResponse(response);
        }
    }

    /**
     * Answer the given member of the receiver as a collection handle.
     *
     * @throws DAVException if there is a problem creating the new handle.
     */
    public CollectionHandle getCollectionHandle(String name) throws DAVException {
        return new CollectionHandle(davClient, getMember(name));
    }

    /**
     * Return the locator of the member of this collection, with the given
     * name.  Does NOT perform a call to the server to check the existence
     * of the member.
     *
     * @param memberName the name of the receiver's internal member.
     * @return the Locator for the member.
     */
    public ILocator getMember(String memberName) {
        Assert.isTrue(locator.getLabel() == null);
        Assert.isTrue(!locator.isStable());
        String parentName = locator.getResourceURL();
        String childName;
        if (parentName.endsWith("/")) //$NON-NLS-1$
            childName = parentName + memberName;
        else
            childName = parentName + "/" + memberName; //$NON-NLS-1$
        return davClient.getDAVFactory().newLocator(childName);
    }

    /**
     * Return a set of handles representing the members of this
     * collection.
     *

     * Each member of the set will be typed to be a ResourceHandle
     * or a CollectionHandle depending upon whether it implements
     * collection semantics.  Note that workspaces will be returned as
     * regular collection handles and should be converted to workspace handles
     * if required (test using isWorkspace()).

     *
     * @return a Set of ResourceHandle and/or
     * CollectionHandle or an empty set if the receiver has no members.
     * @exception DAVException if there was a problem getting the members.
     */
    public Set getMembers() throws DAVException {

        // Query the DAV:resource-type property to depth one.
        Collection querySet = new Vector();
        querySet.add(DAV_RESOURCE_TYPE);
        URLTable resourceTable = getProperties(querySet, IContext.DEPTH_ONE);

        // Create a collection for the reply, and remove
        // ourselves from the answer.
        Set reply = new HashSet();
        try {
            resourceTable.remove(locator.getResourceURL());
        } catch (MalformedURLException exception) {
            throw new DAVException(Policy.bind("exception.malformedLocator")); //$NON-NLS-1$
        }

        // The keys of the result correspond to the receiver's internal members.
        Enumeration resourceNameEnum = resourceTable.keys();
        while (resourceNameEnum.hasMoreElements()) {
            URL url = (URL) resourceNameEnum.nextElement();

            // Get the props for that resource
            Hashtable propertyTable = (Hashtable) resourceTable.get(url);
            Assert.isNotNull(propertyTable);
            PropertyStatus propertyStatus = (PropertyStatus) propertyTable.get(DAV_RESOURCE_TYPE);
            Assert.isNotNull(propertyStatus);

            // If we have a DAV:collection element, then create a collection handle,
            // all other resource types are created as regular resource handles.
            ILocator newLocator = davClient.getDAVFactory().newLocator(url.toString());
            Element property = propertyStatus.getProperty();
            try {
                if (ElementEditor.hasChild(property, DAV_COLLECTION_RESOURCE_TYPE))
                    reply.add(new CollectionHandle(davClient, newLocator));
                else
                    reply.add(new ResourceHandle(davClient, newLocator));
            } catch (MalformedElementException exception) {
                throw new SystemException(exception);
            }
        } // end-while

        return reply;
    }

    public ResourceHandle getResourceHandle(String name) throws DAVException {
        return new ResourceHandle(davClient, getMember(name));
    }

    public WorkspaceHandle getWorkspaceHandle(String name) throws DAVException {
        return new WorkspaceHandle(davClient, getMember(name));
    }

    /**
     * Check to see if the receiver is a workspace resource.
     *

     * The resource is a workspace resource if it has
     * <DAV:workspace-checkout-set> in the
     * <DAV:supported-live-properties-set>.

     *
     * @return true if the resource is a workspace
     * and false otherwise.
     * @throws DAVException if a problem occurs determining the state
     * of the resource.
     */
    public boolean isWorkspace() throws DAVException {
        return supportsLiveProperty(DAV_WORKSPACE_CHECKOUT_SET);
    }
}


/*
 * Copyright 2010 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.drools.eclipse.editors.rete;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.drools.eclipse.reteoo.BaseVertex;

/**
 * Represents one row in rete graph
 */
public class Row {

    private final int depth;

    //List<BaseVertex>
    private List<BaseVertex> vertices;

    /**
     * Default constructor.
     *
     * @param depth row depth
     */
    public Row(final int depth) {
        super();
        this.vertices = new ArrayList<BaseVertex>();
        this.depth = depth;
    }

    /**
     * Returns row depth
     *
     * @return row depth
     */
    public int getDepth() {
        return this.depth;
    }

    /**
     * Adds new vertex to this row.
     *
     * @param vertex new vertex to be added
     */
    public void add(final BaseVertex vertex) {
        this.vertices.add( vertex );
    }

    /**
     * Returns all vertices from this row.
     *
     * @return list of vertices with type BaseVertex
     */
    public List<BaseVertex> getVertices() {
        return this.vertices;
    }

    /**
     * @param vertex
     * @return true if vertex is found in row. false otherwise.
     */
    public boolean contains(final BaseVertex vertex) {
        return this.vertices.contains( vertex );
    }

    /**
     * @return number of vertices in row
     */
    public int getWidth() {
        return this.vertices.size();
    }

    /**
     * Optimizing vertices for optimal presentation
     */
    public void optimize() {
        final List<BaseVertex> sorted = new ArrayList<BaseVertex>( this.vertices );

        Collections.sort(sorted, new Comparator<BaseVertex>() {
            public int compare(final BaseVertex v1, final BaseVertex v2) {
                int v1OutDegree = v1.getSourceConnections().size();
                int v2OutDegree = v2.getSourceConnections().size();

                if (v1OutDegree < v2OutDegree) {
                    return 1;
                }

                if (v1OutDegree > v2OutDegree) {
                    return -1;
                }

                return 0;
            }
        });

        final LinkedList<BaseVertex> optimized = new LinkedList<BaseVertex>();

        boolean front = false;

        for ( final Iterator<BaseVertex> vertexIter = sorted.iterator(); vertexIter.hasNext(); ) {
            final BaseVertex vertex = vertexIter.next();

            if ( front ) {
                optimized.addFirst( vertex );
            } else {
                optimized.addLast( vertex );
            }

            front = !front;
        }

        this.vertices = optimized;
    }
}


/*
 * Copyright 2015 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

package org.eclipse.webdav.internal.authentication;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Constructor;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
import org.eclipse.webdav.IContext;
import org.eclipse.webdav.IResponse;
import org.eclipse.webdav.http.client.IAuthenticator;
import org.eclipse.webdav.http.client.Request;
import org.eclipse.webdav.internal.kernel.utils.Assert;

/**
 * The AuthorizationAuthority authorizes client
 * Request</codes>s for communication with HTTP servers. Subclasses
 * provide the necessary behavior for different authentication schemes.
 */
public class AuthorizationAuthority {

    public static String[] authenticationSchemes = {"Digest", "Basic"}; //$NON-NLS-1$ //$NON-NLS-2$
    protected IAuthenticator authenticatorStore = null;

    /**
     * Creates a new authenticator that stores its authentication information
     * in the given authenticator store.
     *
     * @param authenticatorStore a store that holds authentication
     * information
     */
    public AuthorizationAuthority(IAuthenticator authenticatorStore) {
        Assert.isNotNull(authenticatorStore);
        this.authenticatorStore = authenticatorStore;
    }

    /**
     * Authorizes the given request by setting its authorization credentials
     * in the given context. If the given response is not null,
     * it is assumed to contain an authenticate challenge that is used to
     * derive the authorization credentials. Returns true if the authorization
     * succeeds, and false otherwise.
     *
     * @param request the request to authorize
     * @param response the response containing the authenticate challenge
     * @param context the context where the authorization credentials are set
     * @param proxyServerUrl the URL of the proxy server, or null
     * if there is no proxy server
     * @param isProxyAuthorization a boolean indicating whether the
     * authorization credentials should be computed for the proxy server or
     * the origin server
     * @return a boolean indicating whether the request was successfully
     * authorized
     */
    public boolean authorize(Request request, IResponse response, IContext context, URL proxyServerUrl, boolean isProxyAuthorization) {
        Assert.isNotNull(request);
        Assert.isNotNull(context);

        URL serverUrl = null;
        URL protectionSpaceUrl = null;

        if (isProxyAuthorization) {
            if (proxyServerUrl == null) {
                return false;
            }
            serverUrl = proxyServerUrl;
            protectionSpaceUrl = proxyServerUrl;
        } else {
            URL resourceUrl = request.getResourceUrl();
            try {
                serverUrl = new URL(resourceUrl.getProtocol(), resourceUrl.getHost(), resourceUrl.getPort(), "/"); //$NON-NLS-1$
            } catch (MalformedURLException e) {
                return false;
            }
            protectionSpaceUrl = resourceUrl;
        }

        if (response != null) {
            String challengeString = null;
            if (isProxyAuthorization) {
                challengeString = response.getContext().getProxyAuthenticate();
            } else {
                challengeString = response.getContext().getWWWAuthenticate();
            }

            if (challengeString == null) {
                return false;
            }

            AuthenticateChallenge challenge = null;
            try {
                challenge = new AuthenticateChallenge(challengeString);
            } catch (ParserException e) {
                return false;
            }

            String authScheme = challenge.getAuthScheme();
            String realm = challenge.getRealm();

            AuthorizationAuthority authority = getAuthorizationAuthority(authScheme);
            if (authority == null) {
                return false;
            }

            Map oldInfo = authenticatorStore.getAuthenticationInfo(serverUrl, realm, authScheme);
            Map info = authority.getAuthenticationInfo(challenge, oldInfo, serverUrl, protectionSpaceUrl);
            if (info == null) {
                return false;
            }

            authenticatorStore.addAuthenticationInfo(serverUrl, realm, authScheme, info);
            authenticatorStore.addProtectionSpace(protectionSpaceUrl, realm);
        }

        String realm = authenticatorStore.getProtectionSpace(protectionSpaceUrl);
        if (realm == null) {
            return false;
        }

        Map info = null;
        String authScheme = null;

        for (int i = 0; i < authenticationSchemes.length; ++i) {
            authScheme = authenticationSchemes[i];
            info = authenticatorStore.getAuthenticationInfo(serverUrl, realm, authScheme);
            if (info != null) {
                break;
            }
        }

        if (info == null) {
            return false;
        }

        AuthorizationAuthority authority = getAuthorizationAuthority(authScheme);
        if (authority == null) {
            return false;
        }

        String authorization = authority.getAuthorization(request, info, serverUrl, protectionSpaceUrl, proxyServerUrl);
        if (authorization == null) {
            return false;
        }

        if (isProxyAuthorization) {
            if (authorization.equals(context.getProxyAuthorization()))
                return false; // we already had that auth so it must've failed
            context.setProxyAuthorization(authorization);
        } else {
            if (authorization.equals(context.getAuthorization()))
                return false; // we already had that auth so it must've failed
            context.setAuthorization(authorization);
        }

        return true;
    }

    /**
     * Confirms whether the given response is valid by proving the server
     * knows the client's authentication secret (password). Moreover, the
     * server may wish to communicate some authentication information in the
     * response for the purposes of authorizing future request.
     *
     * @param request the request that has already been sent
     * @param response the response back from the server to be verified
     * @param proxyServerUrl the URL of the proxy server, or null
     * if there is none
     * @returns a boolean indicating whether the given response is valid
     */
    public boolean confirm(Request request, IResponse response, URL proxyServerUrl) {
        Assert.isNotNull(request);
        Assert.isNotNull(response);

        URL resourceUrl = request.getResourceUrl();

        URL serverUrl = null;
        try {
            serverUrl = new URL(resourceUrl.getProtocol(), resourceUrl.getHost(), resourceUrl.getPort(), "/"); //$NON-NLS-1$
        } catch (MalformedURLException e) {
            return false;
        }

        String realm = authenticatorStore.getProtectionSpace(resourceUrl);
        if (realm == null) {
            return false;
        }

        Map info = null;
        String authScheme = null;

        for (int i = 0; i < authenticationSchemes.length; ++i) {
            authScheme = authenticationSchemes[i];
            info = authenticatorStore.getAuthenticationInfo(serverUrl, realm, authScheme);
            if (info != null) {
                break;
            }
        }

        if (info == null) {
            return false;
        }

        AuthorizationAuthority authority = getAuthorizationAuthority(authScheme);
        if (authority == null) {
            return false;
        }

        return authority.confirmResponse(request, response, proxyServerUrl);
    }

    /**
     * Confirms whether the given response is valid by proving the server
     * knows the client's authentication secret (password). Moreover, the
     * server may wish to communicate some authentication information in the
     * response for the purposes of authorizing future request.
     *
This method should be overridden by schema specific authenticators.
     *
     * @param request the request that has already been sent
     * @param response the response back from the server to be verified
     * @param proxyServerUrl the URL of the proxy server, or null
     * if there is none
     * @returns a boolean indicating whether the given response is valid
     */
    protected boolean confirmResponse(Request request, IResponse response, URL proxyServerUrl) {
        Assert.isNotNull(request);
        Assert.isNotNull(response);
        return false;
    }

    /**
     * Returns the new authentication information gleaned from the given
     * authenticate challenge and the given old authentication information.
     * The old authentication information may be null.
     * The authentication information usually contains directives such as
     * usernames and passwords.
     *
This method should be overridden by schema specific authenticators.
     *
     * @param challenge the authenticate challenge from the server
     * @param oldInfo the old authentication information
     * @param serverUrl the URL of the server
     * @param protectionSpaceUrl the URL of the protected resource
     * @return new authentication information
     */
    protected Map getAuthenticationInfo(AuthenticateChallenge challenge, Map oldInfo, URL serverUrl, URL protectionSpaceUrl) {
        Assert.isNotNull(challenge);
        Assert.isNotNull(serverUrl);
        Assert.isNotNull(protectionSpaceUrl);
        return null;
    }

    /**
     * Returns the authorization credentials for the given request. The
     * authorization credentials are derived from the given authentication
     * info. The authentication info may contain directives such as usernames
     * and passwords.
     *
This method should be overridden by schema specific authenticators.
     *
     * @param request the request being authorized
     * @param info the authentication information used to derive the
     * authorization credentials
     * @param serverUrl the URL of the server
     * @param protectionSpaceUrl the URL of the protected resource
     * @param proxyServerUrl the URL of the proxy server, or null
     * if there is none
     * @return the authorization credentials for the given request
     */
    protected String getAuthorization(Request request, Map info, URL serverUrl, URL protectionSpaceUrl, URL proxyServerUrl) {
        Assert.isNotNull(request);
        Assert.isNotNull(info);
        Assert.isNotNull(serverUrl);
        Assert.isNotNull(protectionSpaceUrl);
        return null;
    }

    /**
     * Returns an authorization authority for the given authentication
     * scheme, or null if there is no such authority.
     *
     * @param scheme an authentication scheme, for example: "Basic"
     * @return an authorization authority for the given authentication scheme
     */
    private AuthorizationAuthority getAuthorizationAuthority(String scheme) {
        try {
            scheme = Character.toUpperCase(scheme.charAt(0)) + scheme.substring(1).toLowerCase();
            String packageName = "org.eclipse.webdav.internal.authentication"; //$NON-NLS-1$
            String className = scheme + "Authority"; //$NON-NLS-1$
            Class clazz = Class.forName(packageName + "." + className); //$NON-NLS-1$
            Constructor constructor = clazz.getConstructor(new Class[] {IAuthenticator.class});
            return (AuthorizationAuthority) constructor.newInstance(new Object[] {authenticatorStore});
        } catch (ClassCastException e) {
            // ignore or log?
        } catch (Exception e) {
            // ignore or log?
        }
        return null;
    }

    /**
     * Computes the MD5 hash value of the given String and
     * returns the result as a HEX String.
     *
     * @param s
     * @return a HEX String containing the MD5 hash value of the
     * given String
     * @exception NoSuchAlgorithmException
     * @exception UnsupportedEncodingException
     */
    protected String md5(String s) throws NoSuchAlgorithmException, UnsupportedEncodingException {
        MessageDigest md5 = MessageDigest.getInstance("MD5"); //$NON-NLS-1$
        byte[] hash = md5.digest(s.getBytes("UTF8")); //$NON-NLS-1$
        return HexConverter.toHex(hash);
    }

    /**
     * Computes the MD5 hash value of the body of the given request and
     * returns the result as a HEX String.
     *
     * @param request
     * @return a HEX String containing the MD5 hash value of the
     * body of the given request
     * @exception NoSuchAlgorithmException
     * @exception IOException
     */
    protected String md5(Request request) throws NoSuchAlgorithmException, IOException {
        DigestOutputStream dos = new DigestOutputStream("MD5"); //$NON-NLS-1$
        request.write(dos);
        String result = HexConverter.toHex(dos.digest());
        dos.close();
        return result;
    }

    /**
     * Returns the given String with its quotes removed.
     *
     * @param s a String
     * @return the given String with its quotes removed
     */
    protected String unquote(String s) {
        if (s.charAt(0) == '"' && s.charAt(s.length() - 1) == '"') //$NON-NLS-1$ //$NON-NLS-2$
            return s.substring(1, s.length() - 1);
        return s;
    }
}


/*
 * Copyright 2015 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

package org.eclipse.webdav.internal.kernel;

import java.io.IOException;
import java.io.StreamTokenizer;
import org.eclipse.webdav.IResponse;

/**
 * A ConditionFactor represents some state of a resource that must be
 * satisfied in order for the associated request to be valid. The ConditionFactors in
 * a ConditionTerm must all match with states of the resource, i.e., they are AND'ed
 * together. Conditions are contained in a Precondition which is used in a
 * WebDAV If header. ConditionFactors are either constructed by the client, or may
 * have been given to the client in a previous method request. A ConditionFactor can
 * be either a StateToken or an EntityTag as defined by section 9.4 of the WebDAV
 * spec.
 */
public abstract class ConditionFactor {

    private boolean not = false;

    /**
     * Create a ConditionFactor (either a StateToken or EntityTag) by parsing
     * the tokenizer contining an If header value.
     *
     * @param tokenizer a StreamTokenizer containing the contents of a state token or entity tag
     *    from a WebDAV If header
     * @return the parsed ConditionFactor
     * @exception WebDAVException thrown if there is a syntax error in the If header
     */
    public static ConditionFactor create(StreamTokenizer tokenizer) throws WebDAVException {
        boolean not = false;
        ConditionFactor factor = null;
        try {
            int token = tokenizer.ttype;
            if (token == StreamTokenizer.TT_WORD) {
                if (tokenizer.sval.equalsIgnoreCase("Not")) { //$NON-NLS-1$
                    not = true;
                } else {
                    throw new WebDAVException(IResponse.SC_BAD_REQUEST, Policy.bind("error.parseMissingNot")); //$NON-NLS-1$
                }
                token = tokenizer.nextToken();
            }
            switch (token) {
                case '<' :
                    factor = StateToken.create(tokenizer);
                    break;
                case '[' :
                    factor = EntityTag.create(tokenizer);
                    break;
                default :
                    throw new WebDAVException(IResponse.SC_BAD_REQUEST, Policy.bind("error.parseMissingOpen", String.valueOf(token))); //$NON-NLS-1$
            }
        } catch (IOException exc) {
            // ignore or log?
        }
        factor.setNot(not);
        return factor;
    }

    /**
     * Negate the comparison on this ConditionFactor?
     *
     * @return true if the condition factor was negated in the If header
     */
    public boolean not() {
        return not;
    }

    /**
     * Set how to compare to this ConditionFactor. Value is true implies match for
     * a valid request, false implies the request is valid only if the ConditionFactor
     * doesn't match.
     *
     * @param value true means negate the condition
     */
    public void setNot(boolean value) {
        not = value;
    }

    /**
     * Return a String representation of this ConditionFactor as defined by the If
     * header in section 9.4 of the WebDAV spec.
     *
     * @return a string representation of a state token or entity tag
     */
    public abstract String toString();
}


/*******************************************************************************
 * Copyright (c) 2011, 2012, 2013, 2014 Red Hat, Inc.
 *  All rights reserved.
 * This program is made available under the terms of the
 * Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 * Red Hat, Inc. - initial API and implementation
 *
 ******************************************************************************/

package org.kie.eclipse.server.jbpm770;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.eclipsesource.json.JsonArray;
import com.eclipsesource.json.JsonObject;
import com.eclipsesource.json.JsonValue;
import org.kie.eclipse.server.IKieSpaceHandler;
import org.kie.eclipse.server.IKieProjectHandler;
import org.kie.eclipse.server.IKieRepositoryHandler;
import org.kie.eclipse.server.IKieServerHandler;
import org.kie.eclipse.server.KieSpaceHandler;
import org.kie.eclipse.server.KieProjectHandler;
import org.kie.eclipse.server.KieRepositoryHandler;
import org.kie.eclipse.server.KieServiceDelegate;

public class Kie770Service extends KieServiceDelegate {

    private final Requester requester;

    public Kie770Service() {
        requester = new Requester(this);
    }

    @Override
    public List<IKieSpaceHandler> getSpaces(final IKieServerHandler server) throws IOException {
        final List<IKieSpaceHandler> ret = new ArrayList<IKieSpaceHandler>();

        for (final JsonValue spaceJson : httpGetSpaces()) {
            ret.add(newKieSpaceHandler(server, spaceJson.asObject()));
        }

        return ret;
    }

    @Override
    public List<IKieRepositoryHandler> getRepositories(final IKieServerHandler server) throws IOException {
        final List<IKieRepositoryHandler> ret = new ArrayList<IKieRepositoryHandler>();

        for (final JsonValue spaceJson : httpGetSpaces()) {
            final IKieSpaceHandler space = newKieSpaceHandler(server, spaceJson.asObject());
            for (final JsonValue projectJson : space.getProperties().get("projects").asArray()) {
                ret.add(newKieRepositoryHandler(space, projectJson.asObject()));
            }
        }

        return ret;
    }

    @Override
    public List<IKieRepositoryHandler> getRepositories(final IKieSpaceHandler space) throws IOException {
        final List<IKieRepositoryHandler> ret = new ArrayList<IKieRepositoryHandler>();

        for (final JsonValue projectJson : httpGetRepositories(space)) {
            ret.add(newKieRepositoryHandler(space, projectJson.asObject()));
        }

        return ret;
    }

    @Override
    public List<IKieProjectHandler> getProjects(final IKieRepositoryHandler repository) {
        final IKieProjectHandler project = new KieProjectHandler(repository, repository.getName());
        project.setProperties(repository.getProperties());
        return new ArrayList<IKieProjectHandler>(Collections.singletonList(project));
    }

    private IKieSpaceHandler newKieSpaceHandler(final IKieServerHandler server, final JsonObject spaceJson) {
        final KieSpaceHandler space = new KieSpaceHandler(server, spaceJson.get("name").asString());
        space.setProperties(spaceJson);
        return space;
    }

    private IKieRepositoryHandler newKieRepositoryHandler(final IKieSpaceHandler space, final JsonObject projectJson) {
        final KieRepositoryHandler repository = new KieRepositoryHandler(space, projectJson.get("name").asString());
        repository.setProperties(projectJson);
        return repository;
    }

    @Override
    protected JsonArray httpGetSpaces() throws IOException {
        return JsonArray.readFrom(httpGet("spaces/"));
    }

    @Override
    protected JsonArray httpGetRepositories(final IKieSpaceHandler space) throws IOException {
        return JsonArray.readFrom(httpGet("spaces/" + space.getName() + "/projects"));
    }

    @Override
    public void createSpace(final IKieSpaceHandler space) throws IOException {
        runJob("Request to create space '" + space.getName() + "'", new Requester.Action() {
            @Override
            public String execute() throws IOException {
                return httpPost("spaces/", space.getProperties());
            }
        });
    }

    @Override
    public void deleteSpace(final IKieSpaceHandler space) throws IOException {
        runJob("Request to delete space '" + space.getName() + "'", new Requester.Action() {
            @Override
            public String execute() throws IOException {
                return httpDelete("spaces/" + space.getName());
            }
        });
    }

    @Override
    public void updateSpace(final String oldName, final IKieSpaceHandler space) throws IOException {
        //Updating space properties is not supported yet.
    }

    //Repository

    @Override
    public void createRepository(final IKieRepositoryHandler repository) throws IOException {
        runJob("Request to create repository '" + repository.getName() + "'", new Requester.Action() {
            @Override
            public String execute() throws IOException {
                return httpPost("spaces/" + repository.getParent().getName() + "/projects/", repository.getProperties());
            }
        });
    }

    public void addRepository(final IKieRepositoryHandler repository, final IKieSpaceHandler space) throws IOException {
        //Adding a repository is not supported yet.
    }

    @Override
    public void deleteRepository(final IKieRepositoryHandler repository, final boolean removeOnly) throws IOException {
        final String spaceName = repository.getParent().getName();
        runJob("Request to delete repository '" + repository.getName() + "'", new Requester.Action() {
            @Override
            public String execute() throws IOException {
                return httpDelete("spaces/" + spaceName + "/projects/" + repository.getName());
            }
        });
    }

    @Override
    public void createProject(final IKieProjectHandler project) throws IOException {
        //Creating a project is the same as creating a Repository.
    }

    @Override
    public void deleteProject(final IKieProjectHandler project) throws IOException {
        //Deleting a project is the same as deleting a Repository.
    }

    public void mavenCompile(final IKieProjectHandler project, final JsonObject params) throws IOException {
        final String spaceName = project.getParent().getParent().getName();
        runJob("Request to compile Project '" + project.getName() + "'", new Requester.Action() {
            @Override
            public String execute() throws IOException {
                return httpPost("spaces/" + spaceName + "/projects/" + project.getName() + "/maven/compile/", params);
            }
        });
    }

    public void mavenInstall(final IKieProjectHandler project, final JsonObject params) throws IOException {
        final String spaceName = project.getParent().getParent().getName();
        runJob("Request to install Project '" + project.getName() + "'", new Requester.Action() {
            @Override
            public String execute() throws IOException {
                return httpPost("spaces/" + spaceName + "/projects/" + project.getName() + "/maven/install/", params);
            }
        });
    }

    public void mavenTest(final IKieProjectHandler project, final JsonObject params) throws IOException {
        final String spaceName = project.getParent().getParent().getName();
        runJob("Request to test Project '" + project.getName() + "'", new Requester.Action() {
            @Override
            public String execute() throws IOException {
                return httpPost("spaces/" + spaceName + "/projects/" + project.getName() + "/maven/test/", params);
            }
        });
    }

    public void mavenDeploy(final IKieProjectHandler project, final JsonObject params) throws IOException {
        final String spaceName = project.getParent().getParent().getName();
        runJob("Request to deploy Project '" + project.getName() + "'", new Requester.Action() {
            @Override
            public String execute() throws IOException {
                return httpPost("spaces/" + spaceName + "/projects/" + project.getName() + "/maven/deploy/", params);
            }
        });
    }

    private void runJob(final String title, final Requester.Action action) throws IOException {
        try {
            requester.run(title, action);
        } catch (final JobFailedException e) {
            deleteJob(e.getJobId());
        }
    }

    @Override
    public void updateProject(String oldName, IKieProjectHandler project) throws IOException {
        //Not implemented
    }

    @Override
    public void updateRepository(String oldName, IKieRepositoryHandler repository) throws IOException {
        //Not implemented
    }
}


/*
 * Copyright 2010 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.drools.eclipse.flow.common.editor.action;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.internal.ide.IDEInternalWorkbenchImages;
import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
import org.eclipse.ui.internal.ide.misc.ResourceAndContainerGroup;

public class ExportImageDialog extends TitleAreaDialog {

    private static final String DIALOG_SETTINGS_SECTION = "SaveAsDialogSettings"; //$NON-NLS-1$

    private IFile originalFile = null;

    private String originalName = null;

    private IPath result;

    // widgets
    private ResourceAndContainerGroup resourceGroup;

    private Button okButton;

    /**
     * Image for title area
     */
    private Image dlgTitleImage = null;

    /**
     * Creates a new Save As dialog for no specific file.
     *
     * @param parentShell the parent shell
     */
    public ExportImageDialog(Shell parentShell) {
        super(parentShell);
    }

    protected void configureShell(Shell shell) {
        super.configureShell(shell);
        shell.setText("Export PNG image");
    }

    protected Control createContents(Composite parent) {
        Control contents = super.createContents(parent);
        initializeControls();
        validatePage();
        resourceGroup.setFocus();
        setTitle("Export PNG image");
        dlgTitleImage = IDEInternalWorkbenchImages.getImageDescriptor(
                IDEInternalWorkbenchImages.IMG_DLGBAN_SAVEAS_DLG).createImage();
        setTitleImage(dlgTitleImage);
        setMessage("Export the selected process as a PNG image");
        return contents;
    }

    public boolean close() {
        if (dlgTitleImage != null) {
            dlgTitleImage.dispose();
        }
        return super.close();
    }

    protected void createButtonsForButtonBar(Composite parent) {
        okButton = createButton(parent, IDialogConstants.OK_ID,
                IDialogConstants.OK_LABEL, true);
        createButton(parent, IDialogConstants.CANCEL_ID,
                IDialogConstants.CANCEL_LABEL, false);
    }

    protected Control createDialogArea(Composite parent) {
        // top level composite
        Composite parentComposite = (Composite) super.createDialogArea(parent);

        // create a composite with standard margins and spacing
        Composite composite = new Composite(parentComposite, SWT.NONE);
        GridLayout layout = new GridLayout();
        layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
        layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
        layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
        layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
        composite.setLayout(layout);
        composite.setLayoutData(new GridData(GridData.FILL_BOTH));
        composite.setFont(parentComposite.getFont());

        Listener listener = new Listener() {
            public void handleEvent(Event event) {
                setDialogComplete(validatePage());
            }
        };

        resourceGroup = new ResourceAndContainerGroup(
                composite,
                listener,
                IDEWorkbenchMessages.SaveAsDialog_fileLabel, IDEWorkbenchMessages.SaveAsDialog_file);
        resourceGroup.setAllowExistingResources(true);

        return parentComposite;
    }

    /**
     * Returns the full path entered by the user.
     *

     * Note that the file and container might not exist and would need to be created.
     * See the IFile.create method and the
     * ContainerGenerator class.
     *

     *
     * @return the path, or null if Cancel was pressed
     */
    public IPath getResult() {
        return result;
    }

    /**
     * Initializes the controls of this dialog.
     */
    private void initializeControls() {
        if (originalFile != null) {
            resourceGroup.setContainerFullPath(originalFile.getParent()
                    .getFullPath());
            String fileName = originalFile.getName();
            int index = fileName.lastIndexOf(".");
            if (index != -1) {
                fileName = fileName.substring(0, index);
            }
            fileName += "-image.png";
            resourceGroup.setResource(fileName);
        } else if (originalName != null) {
            resourceGroup.setResource(originalName);
        }
        setDialogComplete(validatePage());
    }

    /* (non-Javadoc)
     * Method declared on Dialog.
     */
    protected void okPressed() {
        // Get new path.
        IPath path = resourceGroup.getContainerFullPath().append(
                resourceGroup.getResource());

        //If the user does not supply a file extension and if the save
        //as dialog was provided a default file name append the extension
        //of the default filename to the new name
        if (path.getFileExtension() == null) {
            if (originalFile != null && originalFile.getFileExtension() != null) {
                path = path.addFileExtension(originalFile.getFileExtension());
            } else if (originalName != null) {
                int pos = originalName.lastIndexOf('.');
                if (++pos > 0 && pos < originalName.length()) {
                    path = path.addFileExtension(originalName.substring(pos));
                }
            }
        }

        // If the path already exists then confirm overwrite.
        IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
        if (file.exists()) {
            String[] buttons = new String[] { IDialogConstants.YES_LABEL,
                    IDialogConstants.NO_LABEL, IDialogConstants.CANCEL_LABEL };
            String question = NLS.bind(
                    IDEWorkbenchMessages.SaveAsDialog_overwriteQuestion, path
                            .toString());
            MessageDialog d = new MessageDialog(getShell(),
                    IDEWorkbenchMessages.Question,
                    null, question, MessageDialog.QUESTION, buttons, 0);
            int overwrite = d.open();
            switch (overwrite) {
            case 0: // Yes
                break;
            case 1: // No
                return;
            case 2: // Cancel
            default:
                cancelPressed();
                return;
            }
        }

        // Store path and close.
        result = path;
        close();
    }

    /**
     * Sets the completion state of this dialog and adjusts the enable state of
     * the Ok button accordingly.
     *
     * @param value true if this dialog is compelete, and
     *  false otherwise
     */
    protected void setDialogComplete(boolean value) {
        okButton.setEnabled(value);
    }

    /**
     * Sets the original file to use.
     *
     * @param originalFile the original file
     */
    public void setOriginalFile(IFile originalFile) {
        this.originalFile = originalFile;
    }

    /**
     * Set the original file name to use.
     * Used instead of setOriginalFile
     * when the original resource is not an IFile.
     * Must be called before create.
     * @param originalName default file name
     */
    public void setOriginalName(String originalName) {
        this.originalName = originalName;
    }

    /**
     * Returns whether this page's visual components all contain valid values.
     *
     * @return true if valid, and false otherwise
     */
    private boolean validatePage() {
        if (!resourceGroup.areAllValuesValid()) {
            if (!resourceGroup.getResource().equals("")) { //$NON-NLS-1$
                setErrorMessage(resourceGroup.getProblemMessage());
            } else {
                setErrorMessage(null);
            }
            return false;
        }

        String resourceName = resourceGroup.getResource();
        IWorkspace workspace = ResourcesPlugin.getWorkspace();

        // Do not allow a closed project to be selected
        IPath fullPath = resourceGroup.getContainerFullPath();
        if (fullPath != null) {
            String projectName = fullPath.segment(0);
            IStatus isValidProjectName = workspace.validateName(projectName, IResource.PROJECT);
            if(isValidProjectName.isOK()) {
                IProject project = workspace.getRoot().getProject(projectName);
                if(!project.isOpen()) {
                    setErrorMessage(IDEWorkbenchMessages.SaveAsDialog_closedProjectMessage);
                    return false;
                }
            }
        }

        IStatus result = workspace.validateName(resourceName, IResource.FILE);
        if (!result.isOK()){
            setErrorMessage(result.getMessage());
            return false;
        }

        setErrorMessage(null);
        return true;
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.window.Dialog#getDialogBoundsSettings()
     *
     * @since 3.2
     */
    protected IDialogSettings getDialogBoundsSettings() {
        IDialogSettings settings = IDEWorkbenchPlugin.getDefault().getDialogSettings();
        IDialogSettings section = settings.getSection(DIALOG_SETTINGS_SECTION);
        if (section == null) {
            section = settings.addNewSection(DIALOG_SETTINGS_SECTION);
        }
        return section;
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.jface.dialogs.Dialog#isResizable()
     */
    protected boolean isResizable() {
        return true;
    }
}


/*
 * Copyright 2015 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

package org.eclipse.webdav.internal.kernel;

import java.io.IOException;
import java.io.StreamTokenizer;
import org.eclipse.webdav.IResponse;

/**
 * An EntityTag is a ConditionFactor describing some state of a resource represented
 * as an opaque string. See section 3.11 of the HTTP/1.1 spec.
 */
public class EntityTag extends ConditionFactor {

    private static int bcnt = 0;
    private static String basetime = Long.toHexString(new java.util.Date().getTime());

    private String eTag = null;
    // represents some state of a resource expressed as a ETag
    private boolean weak = false;

    /**
     * Construct a EntityTag. Should never be called.
     */
    private EntityTag() {
        super();
    }

    /**
     * Construct a EntityTag with the given opaque string tag.
     *
     * @param tag the opaque string defining the entity tag
     */
    public EntityTag(String tag) {
        this.eTag = tag;
    }

    /**
     * Create an EntityTag by parsing the given If header as defined by
     * section 3.11 of the HTTP/1.1 spec.
     *
     * @param tokenizer a StreamTokenizer on the contents of a WebDAV If header
     * @return the parsed ConditionFactor (EntityTag)
     * @exception WebDAVException thrown if there is a syntax error in the If header
     */
    public static ConditionFactor create(StreamTokenizer tokenizer) throws WebDAVException {
        EntityTag entityTag = new EntityTag();
        try {
            int token = tokenizer.ttype;
            if (token == '[')
                token = tokenizer.nextToken();
            else
                throw new WebDAVException(IResponse.SC_BAD_REQUEST, Policy.bind("error.parseMissing", String.valueOf(token), "[")); //$NON-NLS-1$ //$NON-NLS-2$
            if (token == '"') { //$NON-NLS-1$
                entityTag.setETag(tokenizer.sval);
                token = tokenizer.nextToken();
            } else
                throw new WebDAVException(IResponse.SC_BAD_REQUEST, Policy.bind("error.parseMissingQuotedString", String.valueOf(token))); //$NON-NLS-1$
            if (token == ']')
                token = tokenizer.nextToken();
            else
                throw new WebDAVException(IResponse.SC_BAD_REQUEST, Policy.bind("error.parseMissing", String.valueOf(token), "]")); //$NON-NLS-1$ //$NON-NLS-2$
        } catch (IOException exc) {
            // ignore or log?
        }
        return entityTag;
    }

    /**
     * Compare with another EntityTag.
     *
     * @param etag the entity tag to compare
     * @return true if the tags are equal, false otherwise
     */
    public boolean equals(Object etag) {
        return etag != null && etag instanceof EntityTag && getETag().equals(((EntityTag) etag).getETag());
    }

    /**
     * Construct a unique EntityTag. The tag is constructed by concatening the
     * current time with the current thread's hash code.
     *
     * @return a unique entity tag that servers may use for any purpose
     */
    public static EntityTag generateEntityTag() {
        String xx = basetime + ":" + Integer.toHexString(Thread.currentThread().hashCode()); //$NON-NLS-1$
        bcnt++;
        xx += ":" + bcnt; //$NON-NLS-1$
        return new EntityTag(xx);
    }

    /**
     * Get the ETag of this EntityTag. The ETag represents some state of the
     * resource in the containing Condition.
     *
     * @return the etag
     */
    public String getETag() {
        return eTag;
    }

    /**
     * Is this a weak EntityTag?
     *
     * @return true if this is a weak entity tag
     */
    public boolean isWeak() {
        return weak;
    }

    /**
     * Set the ETag of this EntityTag. The ETag represents some state of the
     * resource in the containing Condition, for example, the lock token.
     *
     * @value the etag to set
     */
    public void setETag(String value) {
        eTag = value;
    }

    /**
     * Set the strength of this EntityTag.
     * value true indicates this is a weak entity tag
     */
    public void setWeak(boolean value) {
        weak = value;
    }

    /**
     * Return a String representation of this EntityTag as defined by the If
     * header in section 9.4 of the WebDAV spec.
     *
     * @return a string representation of this entity tag
     */
    public String toString() {
        StringBuffer buffer = new StringBuffer();
        if (not())
            buffer.append("Not "); //$NON-NLS-1$
        if (isWeak())
            buffer.append("W/"); //$NON-NLS-1$
        buffer.append("[\""); //$NON-NLS-1$
        buffer.append(getETag());
        buffer.append("\"]"); //$NON-NLS-1$
        return buffer.toString();
    }
}


/*
 * Copyright 2015 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

package org.eclipse.webdav.client;

import java.io.IOException;
import org.eclipse.webdav.ILocator;
import org.eclipse.webdav.IResponse;
import org.eclipse.webdav.dom.Mkworkspace;
import org.eclipse.webdav.internal.kernel.DAVException;
import org.eclipse.webdav.internal.kernel.SystemException;
import org.w3c.dom.Document;

/**
 *

 * Note: This class/interface is part of an interim API that is still under
 * development and expected to change significantly before reaching stability.
 * It is being made available at this early stage to solicit feedback from pioneering
 * adopters on the understanding that any code that uses this API will almost
 * certainly be broken (repeatedly) as the API evolves.
 *

 */
public class WorkspaceHandle extends CollectionHandle {

    public WorkspaceHandle(DAVClient davClient, ILocator locator) {
        super(davClient, locator);
    }

    /**
     * Check out this resource. Returns a resource handle on the checked out
     * version selector, or the working resource if a version is checked out.
     */
    public AbstractResourceHandle checkOut() throws DAVException {
        ILocator locator = protectedCheckOut();
        return new WorkspaceHandle(davClient, locator);
    }

    /**
     * Create a new workspace in the location described by this handle.
     *

     * A new workspace is created using a MKWORKSPACE method call.

     *
     * @throws DAVException if a problem occured creating the workspace
     * on the WebDAV server.
     */
    public void create() throws DAVException {
        Document document = newDocument();
        Mkworkspace.create(document);
        IResponse response = null;
        try {
            response = davClient.mkworkspace(locator, newContext(), document);
            examineResponse(response);
        } catch (IOException e) {
            throw new SystemException(e);
        } finally {
            closeResponse(response);
        }
    }
}


/*
 * Copyright 2010 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.drools.eclipse.editors.rete.model;

import org.drools.eclipse.reteoo.BaseVertex;

/**
 * A connection between two distinct vertices.
 */
public class Connection extends ModelElement {

    private boolean    isConnected;

    private BaseVertex source;

    private BaseVertex target;

    /**
     * Creating a connection between two distinct vertices.
     *
     * @param source a source endpoint
     * @param target a target endpoint
     * @throws IllegalArgumentException if any of the parameters are null or source == target
     */
    public Connection(BaseVertex source,
                      BaseVertex target) {
        this.source = source;
        this.target = target;
        source.addConnection( this );
        target.addConnection( this );
        isConnected = true;
    }

    /**
     * Disconnect this connection from the vertices it is attached to.
     */
    public void disconnect() {
        if ( isConnected ) {
            source.removeConnection( this );
            target.removeConnection( this );
            isConnected = false;
        }
    }

    /**
     * Returns the source endpoint of this connection.
     *
     * @return BaseVertex vertex
     */
    public BaseVertex getSource() {
        return source;
    }

    /**
     * Returns the target endpoint of this connection.
     *
     * @return BaseVertex vertex
     */
    public BaseVertex getTarget() {
        return target;
    }

    /**
     * Gets opposite of specified vertex.
     *
     * Returning null if specified not does not belong into this connection.
     *
     * @param vertex
     * @return opposite of vertex
     */
    public BaseVertex getOpposite(BaseVertex vertex) {
        // If null or not part of this connection
        if ( vertex == null || (!vertex.equals( getSource() ) && !vertex.equals( getTarget() )) ) {
            return null;
        }
        if ( vertex.equals( getSource() ) ) {
            return getTarget();
        }
        return getSource();
    }

}