/*
 * Thrifty
 *
 * Copyright (c) Microsoft Corporation
 *
 * All rights reserved.
 *
 * 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
 *
 * THIS CODE IS PROVIDED ON AN  *AS IS* BASIS, WITHOUT WARRANTIES OR
 * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
 * WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE,
 * FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
 *
 * See the Apache Version 2.0 License for specific language governing permissions and limitations under the License.
 */
package com.microsoft.thrifty.protocol;

import com.microsoft.thrifty.TType;
import com.microsoft.thrifty.transport.Transport;
import okio.ByteString;

import java.io.EOFException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.ProtocolException;

/**
 * An implementation of the simple Thrift binary protocol.
 *
 *
Instances of this class are not threadsafe.
 */
public class BinaryProtocol extends Protocol {
    private static final int VERSION_MASK = 0xffff0000;
    private static final int VERSION_1 = 0x80010000;

    private static final StructMetadata NO_STRUCT = new StructMetadata("");

    /**
     * The maximum number of bytes to read from the transport for variable-length
     * fields (strings or binary), or -1 for unlimited.
     */
    private final long stringLengthLimit;

    /**
     * The maximum number of elements to read from the network for containers
     * (maps, lists, sets).
     */
    private final long containerLengthLimit;

    /**
     * A shared buffer for writing.
     */
    private final byte[] buffer = new byte[8];

    private boolean strictRead;
    private boolean strictWrite;

    public BinaryProtocol(Transport transport) {
        this(transport, -1, -1);
    }

    public BinaryProtocol(Transport transport, int stringLengthLimit) {
        this(transport, stringLengthLimit, -1);
    }

    public BinaryProtocol(Transport transport, int stringLengthLimit, int containerLengthLimit) {
        super(transport);
        this.stringLengthLimit = stringLengthLimit;
        this.containerLengthLimit = containerLengthLimit;
    }

    @Override
    public void writeMessageBegin(String name, byte typeId, int seqId) throws IOException {
        if (strictWrite) {
            int version = VERSION_1 | (typeId & 0xFF);
            writeI32(version);
            writeString(name);
            writeI32(seqId);
        } else {
            writeString(name);
            writeByte(typeId);
            writeI32(seqId);
        }
    }

    @Override
    public void writeMessageEnd() throws IOException {
    }

    @Override
    public void writeStructBegin(String structName) throws IOException {
    }

    @Override
    public void writeStructEnd() throws IOException {
    }

    @Override
    public void writeFieldBegin(String fieldName, int fieldId, byte typeId) throws IOException {
        writeByte(typeId);
        writeI16((short) fieldId);
    }

    @Override
    public void writeFieldEnd() throws IOException {
    }

    @Override
    public void writeFieldStop() throws IOException {
        writeByte(TType.STOP);
    }

    @Override
    public void writeMapBegin(byte keyTypeId, byte valueTypeId, int mapSize) throws IOException {
        writeByte(keyTypeId);
        writeByte(valueTypeId);
        writeI32(mapSize);
    }

    @Override
    public void writeMapEnd() throws IOException {
    }

    @Override
    public void writeListBegin(byte elementTypeId, int listSize) throws IOException {
        writeByte(elementTypeId);
        writeI32(listSize);
    }

    @Override
    public void writeListEnd() throws IOException {
    }

    @Override
    public void writeSetBegin(byte elementTypeId, int setSize) throws IOException {
        writeByte(elementTypeId);
        writeI32(setSize);
    }

    @Override
    public void writeSetEnd() throws IOException {
    }

    @Override
    public void writeBool(boolean b) throws IOException {
        writeByte(b ? (byte) 1 : (byte) 0);
    }

    @Override
    public void writeByte(byte b) throws IOException {
        buffer[0] = b;

        transport.write(buffer, 0, 1);
    }

    @Override
    public void writeI16(short i16) throws IOException {
        buffer[0] = (byte) ((i16 >> 8) & 0xFF);
        buffer[1] = (byte) (i16 & 0xFF);

        transport.write(buffer, 0, 2);
    }

    @Override
    public void writeI32(int i32) throws IOException {
        buffer[0] = (byte) ((i32 >> 24) & 0xFF);
        buffer[1] = (byte) ((i32 >> 16) & 0xFF);
        buffer[2] = (byte) ((i32 >>  8) & 0xFF);
        buffer[3] = (byte)  (i32        & 0xFF);

        transport.write(buffer, 0, 4);
    }

    @Override
    public void writeI64(long i64) throws IOException {
        buffer[0] = (byte) ((i64 >> 56) & 0xFF);
        buffer[1] = (byte) ((i64 >> 48) & 0xFF);
        buffer[2] = (byte) ((i64 >> 40) & 0xFF);
        buffer[3] = (byte) ((i64 >> 32) & 0xFF);
        buffer[4] = (byte) ((i64 >> 24) & 0xFF);
        buffer[5] = (byte) ((i64 >> 16) & 0xFF);
        buffer[6] = (byte) ((i64 >>  8) & 0xFF);
        buffer[7] = (byte)  (i64        & 0xFF);

        transport.write(buffer, 0, 8);
    }

    @Override
    public void writeDouble(double dub) throws IOException {
        writeI64(Double.doubleToLongBits(dub));
    }

    @Override
    public void writeString(String str) throws IOException {
        try {
            byte[] bs = str.getBytes("UTF-8");
            writeI32(bs.length);
            transport.write(bs);
        } catch (UnsupportedEncodingException e) {
            throw new AssertionError(e);
        }
    }

    @Override
    public void writeBinary(ByteString buf) throws IOException {
        writeI32(buf.size());
        transport.write(buf.toByteArray());
    }

    //////////////////////

    @Override
    public MessageMetadata readMessageBegin() throws IOException {
        int size = readI32();
        if (size < 0) {
            int version = size & VERSION_MASK;
            if (version != VERSION_1) {
                throw new ProtocolException("Bad version in readMessageBegin");
            }
            return new MessageMetadata(readString(), (byte) (size & 0xff), readI32());
        } else {
            if (strictRead) {
                throw new ProtocolException("Missing version in readMessageBegin");
            }
            return new MessageMetadata(readStringWithSize(size), readByte(), readI32());
        }
    }

    @Override
    public void readMessageEnd() throws IOException {
    }

    @Override
    public StructMetadata readStructBegin() throws IOException {
        return NO_STRUCT;
    }

    @Override
    public void readStructEnd() throws IOException {

    }

    @Override
    public FieldMetadata readFieldBegin() throws IOException {
        byte typeId = readByte();
        short fieldId = typeId == TType.STOP ? 0 : readI16();
        return new FieldMetadata("", typeId, fieldId);
    }

    @Override
    public void readFieldEnd() throws IOException {
    }

    @Override
    public MapMetadata readMapBegin() throws IOException {
        byte keyTypeId = readByte();
        byte valueTypeId = readByte();
        int size = readI32();
        if (containerLengthLimit != -1 && size > containerLengthLimit) {
            throw new ProtocolException("Container size limit exceeded");
        }
        return new MapMetadata(keyTypeId, valueTypeId, size);
    }

    @Override
    public void readMapEnd() throws IOException {
    }

    @Override
    public ListMetadata readListBegin() throws IOException {
        byte elementTypeId = readByte();
        int size = readI32();
        if (containerLengthLimit != -1 && size > containerLengthLimit) {
            throw new ProtocolException("Container size limit exceeded");
        }
        return new ListMetadata(elementTypeId, size);
    }

    @Override
    public void readListEnd() throws IOException {
    }

    @Override
    public SetMetadata readSetBegin() throws IOException {
        byte elementTypeId = readByte();
        int size = readI32();
        if (containerLengthLimit != -1 && size > containerLengthLimit) {
            throw new ProtocolException("Container size limit exceeded");
        }
        return new SetMetadata(elementTypeId, size);
    }

    @Override
    public void readSetEnd() throws IOException {
    }

    @Override
    public boolean readBool() throws IOException {
        return readByte() == 1;
    }

    @Override
    public byte readByte() throws IOException {
        readFully(buffer, 1);
        return buffer[0];
    }

    @Override
    public short readI16() throws IOException {
        readFully(buffer, 2);
        return (short) (((buffer[0] & 0xFF) << 8)
                       | (buffer[1] & 0xFF));
    }

    @Override
    public int readI32() throws IOException {
        readFully(buffer, 4);

        return ((buffer[0] & 0xFF) << 24)
             | ((buffer[1] & 0xFF) << 16)
             | ((buffer[2] & 0xFF) <<  8)
             |  (buffer[3] & 0xFF);
    }

    @Override
    public long readI64() throws IOException {
        readFully(buffer, 8);

        return ((buffer[0] & 0xFFL) << 56)
             | ((buffer[1] & 0xFFL) << 48)
             | ((buffer[2] & 0xFFL) << 40)
             | ((buffer[3] & 0xFFL) << 32)
             | ((buffer[4] & 0xFFL) << 24)
             | ((buffer[5] & 0xFFL) << 16)
             | ((buffer[6] & 0xFFL) <<  8)
             |  (buffer[7] & 0xFFL);
    }

    @Override
    public double readDouble() throws IOException {
        return Double.longBitsToDouble(readI64());
    }

    @Override
    public String readString() throws IOException {
        int sizeInBytes = readI32();
        if (stringLengthLimit != -1 && sizeInBytes > stringLengthLimit) {
            throw new ProtocolException("String size limit exceeded");
        }

        return readStringWithSize(sizeInBytes);
    }

    @Override
    public ByteString readBinary() throws IOException {
        int sizeInBytes = readI32();
        if (stringLengthLimit != -1 && sizeInBytes > stringLengthLimit) {
            throw new ProtocolException("Binary size limit exceeded");
        }
        byte[] data = new byte[sizeInBytes];
        readFully(data, data.length);
        return ByteString.of(data);
    }

    private String readStringWithSize(int size) throws IOException {
        byte[] encoded = new byte[size];
        readFully(encoded, size);
        return new String(encoded, "UTF-8");
    }

    private void readFully(byte[] buffer, int count) throws IOException {
        int toRead = count;
        int offset = 0;
        while (toRead > 0) {
            int read = transport.read(buffer, offset, toRead);
            if (read == -1) {
                throw new EOFException("Expected " + count + " bytes; got " + offset);
            }
            toRead -= read;
            offset += read;
        }
    }
}


/*
 * Thrifty
 *
 * Copyright (c) Microsoft Corporation
 *
 * All rights reserved.
 *
 * 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
 *
 * THIS CODE IS PROVIDED ON AN  *AS IS* BASIS, WITHOUT WARRANTIES OR
 * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
 * WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE,
 * FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
 *
 * See the Apache Version 2.0 License for specific language governing permissions and limitations under the License.
 */
package com.microsoft.thrifty.service;

import com.microsoft.thrifty.Struct;
import com.microsoft.thrifty.ThriftException;
import com.microsoft.thrifty.protocol.Protocol;

import java.io.Closeable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionException;

/**
 * Implements a basic service client that executes methods asynchronously.
 *
 *
Note that, while the client-facing API of this class is callback-based,
 * the implementation itself is blocking.  Unlike the Apache
 * implementation, there is no presumption made here about framed encoding
 * at the transport level.  If your backend requires framing, be sure to
 * configure your {@link Protocol} and {@link com.microsoft.thrifty.transport.Transport}
 * objects appropriately.
 */
public class AsyncClientBase extends ClientBase implements Closeable {
    /**
     * Exposes important events in the client's lifecycle.
     */
    public interface Listener {
        /**
         * Invoked when the client connection has been closed.
         *
         *
After invocation, the client is no longer usable.  All subsequent
         * method call attempts will result in an immediate exception on the
         * calling thread.
         */
        void onTransportClosed();

        /**
         * Invoked when a client-level error has occurred.
         *
         *
This generally indicates a connectivity or protocol error,
         * and is distinct from errors returned as part of normal service
         * operation.
         *
         *
The client is guaranteed to have been closed and shut down
         * by the time this method is invoked.
         *
         * @param error the throwable instance representing the error.
         */
        void onError(Throwable error);
    }

    /**
     * A single-thread executor on which to invoke method callbacks.
     *
     *
I expect that we'll revisit this design choice; it guarantees
     * that method responses won't race each other, but arguably that's
     * a higher-level concern, and this does feel a bit heavy-handed.
     */
    private final ExecutorService callbackExecutor = Executors.newSingleThreadExecutor();

    /**
     * An unbounded queue holding RPC calls awaiting execution.
     */
    private final BlockingQueue<MethodCall<?>> pendingCalls = new LinkedBlockingQueue<>();

    private final Listener listener;
    private final WorkerThread workerThread;

    protected AsyncClientBase(Protocol protocol, Listener listener) {
        super(protocol);
        this.listener = listener;
        this.workerThread = new WorkerThread();

        workerThread.setDaemon(true);
        workerThread.start();
    }

    /**
     * When invoked by a derived instance, places the given call in a queue to
     * be sent to the server.
     *
     * @param methodCall the remote method call to be invoked
     */
    protected void enqueue(MethodCall<?> methodCall) {
        if (!running.get()) {
            throw new IllegalStateException("Cannot write to a closed service client");
        }

        if (!pendingCalls.offer(methodCall)) {
            // This should never happen with an unbounded queue
            throw new IllegalStateException("Call queue is full");
        }
    }

    @Override
    public void close() throws IOException {
        close(null);
    }

    private void close(final Throwable error) {
        if (!running.compareAndSet(true, false)) {
            return;
        }

        workerThread.interrupt();

        closeProtocol();

        if (!pendingCalls.isEmpty()) {
            List<MethodCall<?>> incompleteCalls = new ArrayList<>();
            pendingCalls.drainTo(incompleteCalls);
            CancellationException e = new CancellationException();
            for (MethodCall<?> call : incompleteCalls) {
                try {
                    fail(call, e);
                } catch (Exception ignored) {
                    // nope
                }
            }
        }

        callbackExecutor.execute(new Runnable() {
            @Override
            public void run() {
                if (error != null) {
                    listener.onError(error);
                } else {
                    listener.onTransportClosed();
                }
            }
        });

        try {
            // Shut down, but let queued tasks finish.
            // Don't terminate!
            callbackExecutor.shutdown();
        } catch (Exception ignored) {
            // nope
        }
    }

    @SuppressWarnings("unchecked")
    private class WorkerThread extends Thread {
        @Override
        public void run() {
            Throwable error = null;
            while (running.get()) {
                try {
                    invokeRequest();
                } catch (Throwable e) {
                    error = e;
                    break;
                }
            }

            try {
                close(error);
            } catch (Throwable ignored) {
                // nope
            }
        }

        private void invokeRequest() throws ThriftException, IOException, InterruptedException {
            MethodCall<?> call = pendingCalls.take();
            if (!running.get()) {
                if (call != null) {
                    fail(call, new CancellationException());
                }
                return;
            }

            if (call == null) {
                return;
            }

            Object result = null;
            Exception error = null;
            try {
                result = AsyncClientBase.this.invokeRequest(call);
            } catch (IOException | RuntimeException e) {
                throw e;
            } catch (ServerException e) {
                error = e.thriftException;
            } catch (Exception e) {
                if (e instanceof Struct) {
                    error = e;
                } else {
                    // invokeRequest should only throw one of the caught Exception types or
                    // an Exception extending Struct from MethodCall
                    throw new AssertionError("Unexpected exception", e);
                }
            }

            try {
                if (error != null) {
                    fail(call, error);
                } else {
                    complete(call, result);
                }
            } catch (RejectedExecutionException e) {
                // The client has been closed out from underneath; as there will
                // be no further use for this thread, no harm in running it
                // synchronously.
                if (error != null) {
                    call.callback.onError(error);
                } else {
                    //noinspection RedundantCast
                    ((MethodCall) call).callback.onSuccess(result);
                }
            }
        }
    }

    private void complete(final MethodCall call, final Object result) {
        callbackExecutor.execute(new Runnable() {
            @SuppressWarnings("unchecked")
            @Override
            public void run() {
                call.callback.onSuccess(result);
            }
        });
    }

    private void fail(final MethodCall<?> call, final Throwable error) {
        callbackExecutor.execute(new Runnable() {
            @Override
            public void run() {
                call.callback.onError(error);
            }
        });
    }
}


/*
 * 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;

import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IStorage;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.ui.IDecoratorManager;
import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.IStorageEditorInput;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.guvnor.tools.Activator;
import org.guvnor.tools.GuvnorDecorator;
import org.guvnor.tools.Messages;
import org.guvnor.tools.utils.webdav.IWebDavClient;
import org.guvnor.tools.utils.webdav.WebDavClientFactory;
import org.guvnor.tools.utils.webdav.WebDavServerCache;
import org.guvnor.tools.utils.webdav.WebDavSessionAuthenticator;
import org.guvnor.tools.views.IGuvnorConstants;
import org.guvnor.tools.views.RepositoryView;
import org.guvnor.tools.views.ResourceHistoryView;

/**
 * A set of utilities for interacting with the Eclipse platform.
 */
public class PlatformUtils {

    private static PlatformUtils instance;

    /**
     * For convenience, we keep one instance of PlatformUtils around
     * @return the PlatformUtils instance
     */
    public static PlatformUtils getInstance() {
        if (instance == null) {
            instance = new PlatformUtils();
        }
        return instance;
    }

    /**
     * Resolves a file system location to an Eclipse workspace resource.
     * @param location The file system location
     * @return The Eclipse IFile, null if not found
     */
    public static IFile getResourceFromFSPath(String location) {
        return Activator.getDefault().getWorkspace().
                getRoot().getFileForLocation(new Path(location));
    }

    public static Composite createComposite(Composite parent, int numColumns) {
        Composite composite = new Composite(parent, SWT.NULL);

        GridLayout layout = new GridLayout();
        layout.numColumns = numColumns;
        composite.setLayout(layout);
        composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        return composite;
    }

    /**
     * Causes the platform to update Guvnor decoration notions.
     */
    public static void updateDecoration() {
        final IWorkbench workbench = Activator.getDefault().getWorkbench();
        workbench.getDisplay().syncExec(new Runnable() {
            public void run() {
                IDecoratorManager manager = workbench.getDecoratorManager();
                manager.update(GuvnorDecorator.DECORATOR_ID);
            }
        });
    }

    /**
     * Causes the Repository view to refresh, if it is open.
     */
    public static void refreshRepositoryView() {
        IWorkbenchWindow activeWindow = Activator.getDefault().
                                            getWorkbench().getActiveWorkbenchWindow();
        // If there is no active workbench window, then there can be no Repository view
        if (activeWindow == null) {
            return;
        }
        // If there is no active workbench page, then there can be no Repository view
        IWorkbenchPage page = activeWindow.getActivePage();
        if (page == null) {
            return;
        }
        RepositoryView view = (RepositoryView)page.findView(IGuvnorConstants.REPVIEW_ID);
        if (view != null) {
            view.refresh();
        }
    }

    /**
     * Tries to find the Resource History view, attempting to open it if necessary.
     */
    public static ResourceHistoryView getResourceHistoryView() throws Exception {
        IWorkbenchWindow activeWindow = Activator.getDefault().
                                            getWorkbench().getActiveWorkbenchWindow();
        // If there is no active workbench window, then there can be no Repository History view
        if (activeWindow == null) {
            return null;
        }
        // If there is no active workbench page, then there can be no Repository History view
        IWorkbenchPage page = activeWindow.getActivePage();
        if (page == null) {
            return null;
        }
        return (ResourceHistoryView)page.showView(IGuvnorConstants.RESHISTORYVIEW_ID);
    }

    /**
     * Opens a read-only, in-memory editor.
     * @param contents The contents for the editor
     * @param name The name of the file. Will be used to determine
     *        eclipse editor association, defaulting to text editor
     *        if no association is found
     */
    public static void openEditor(String contents, String name) {
        IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
        IStorage storage = new StringStorage(contents, name);
        IStorageEditorInput input = new StringInput(storage);
        IWorkbenchPage page = window.getActivePage();
        IEditorDescriptor desc = PlatformUI.getWorkbench().
                                    getEditorRegistry().getDefaultEditor(name);
        // If there is no editor associated with the given file name, we'll just
        // use the eclipse text editor as a default
        String editorId = desc != null?desc.getId():"org.eclipse.ui.DefaultTextEditor"; //$NON-NLS-1$
        try {
        if (page != null) {
            page.openEditor(input, editorId);
        }
        } catch (Exception e) {
            Activator.getDefault().displayError(IStatus.ERROR, e.getMessage(), e, true);
        }
    }

    public static Table createResourceHistoryTable(Composite parent) {
        int style = SWT.SINGLE | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL |
                    SWT.FULL_SELECTION | SWT.HIDE_SELECTION;

        Table table = new Table(parent, style);

        GridData gridData = new GridData(GridData.FILL_BOTH);
        gridData.grabExcessVerticalSpace = true;
        gridData.horizontalSpan = 3;
        table.setLayoutData(gridData);

        table.setLinesVisible(true);
        table.setHeaderVisible(true);

        TableColumn column = new TableColumn(table, SWT.LEFT, 0);
        column.setResizable(true);
        column.setText(Messages.getString("history.revision")); //$NON-NLS-1$
        column.setWidth(100);

        column = new TableColumn(table, SWT.LEFT, 1);
        column.setResizable(true);
        column.setText(Messages.getString("history.date")); //$NON-NLS-1$
        column.setWidth(175);

        column = new TableColumn(table, SWT.LEFT, 2);
        column.setResizable(true);
        column.setText(Messages.getString("history.author")); //$NON-NLS-1$
        column.setWidth(200);

        column = new TableColumn(table, SWT.CENTER, 3);
        column.setResizable(true);
        column.setText(Messages.getString("history.comment")); //$NON-NLS-1$
        column.setWidth(350);

        return table;
    }

    public boolean authenticateForServer(String server, IWebDavClient client) throws Exception {
        AuthPromptResults res = promptForAuthentication(server);
        if (res != null) {
            if (res.wasSaved()) {
                Platform.addAuthorizationInfo(new URL(server), "", "basic", res.getAuthInfo()); //$NON-NLS-1$ //$NON-NLS-2$
            } else {
                WebDavSessionAuthenticator authen = new WebDavSessionAuthenticator();
                authen.addAuthenticationInfo(new URL(server), "", "basic", res.getAuthInfo()); //$NON-NLS-1$ //$NON-NLS-2$
                client.setSessionAuthenticator(authen);
            }
            return true;
        } else {
            return false;
        }
    }

    public void updateAuthentication(String server, String username,
                                    String password, boolean saveInfo) throws Exception {
        Map<String, String> info = new HashMap<String, String>();
        info.put("username", username); //$NON-NLS-1$
        info.put("password", password); //$NON-NLS-1$
        URL serverUrl = new URL(server);
        IWebDavClient client = WebDavServerCache.getWebDavClient(server);
        if (client == null) {
            client = WebDavClientFactory.createClient(serverUrl);
            WebDavServerCache.cacheWebDavClient(server, client);
        }
        if (saveInfo) {
            Platform.flushAuthorizationInfo(serverUrl, "", "basic"); //$NON-NLS-1$ //$NON-NLS-2$
            Platform.addAuthorizationInfo(serverUrl, "", "basic", info); //$NON-NLS-1$ //$NON-NLS-2$
        } else {
            WebDavSessionAuthenticator authen = new WebDavSessionAuthenticator();
            authen.addAuthenticationInfo(new URL(server), "", "basic", info); //$NON-NLS-1$ //$NON-NLS-2$
            client.setSessionAuthenticator(authen);
        }
    }

    /**
     * Convenience method for reporting log in failure
     */
    public static void reportAuthenticationFailure() {
        Display display = PlatformUI.getWorkbench().getDisplay();
        display.asyncExec(new Runnable() {
            public void run() {
                Display display = Display.getCurrent();
                Shell shell = display.getActiveShell();
                MessageDialog.openError(shell, Messages.getString("login.failure.dialog.caption"),  //$NON-NLS-1$
                                       Messages.getString("login.failure.dialog.message")); //$NON-NLS-1$
            }
        });
    }

    /**
     * Prompts for user name and password for a given Guvnor repository.
     * @param server The repository for log in
     * @return The dialog results. Includes whether the user decided to save
     *         the user name and password in the platform's key ring.
     *         Null if the user cancels the dialog.
     */
    public AuthPromptResults promptForAuthentication(final String server) {

        Display display = PlatformUI.getWorkbench().getDisplay();
        AuthPromptRunnable op = new AuthPromptRunnable(server);
        display.syncExec(op);
        return op.getResults();
    }

    /**
     * An operation for running a log in dialog in the next
     * available UI thread.
     */
    class AuthPromptRunnable implements Runnable {
        AuthPromptResults res = null;
        private String server;

        public AuthPromptRunnable(String server) {
            this.server = server;
        }

        public void run() {
            Display display = Display.getCurrent();
            Shell shell = display.getActiveShell();
            AuthenticationPromptDialog diag = new AuthenticationPromptDialog(shell, server);
            if (diag.open() == Dialog.OK) {
                Map<String, String> info = new HashMap<String, String>();
                info.put("username", diag.getUserName()); //$NON-NLS-1$
                info.put("password", diag.getPassword()); //$NON-NLS-1$
                res = new AuthPromptResults(info, diag.saveAuthenInfo());
            }
        }

        public AuthPromptResults getResults() {
            return res;
        }
    }

    /**
     * The results from a log in dialog prompt.
     */
    public class AuthPromptResults {
        // username and password
        private Map<String, String> info;
        // whether the user wants to save the authentication information
        // in the platform's key ring file
        private boolean saved;

        public AuthPromptResults(Map<String, String> info, boolean saved) {
            this.info = info;
            this.saved = saved;
        }

        public Map<String, String> getAuthInfo() {
            return info;
        }

        public boolean wasSaved() {
            return saved;
        }
    }
}


/*
 * 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.http.client;

import java.util.Vector;
import org.eclipse.webdav.internal.kernel.utils.Assert;

/**
 * A BufferPool holds on to a collection of buffers (byte
 * arrays) so they can be reused without having to allocate and release
 * memory.
 *

 * 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 BufferPool {
    /**
     * The size of each buffer in the pool.
     */
    private static int BUFFER_SIZE = 8 * 1024;

    /**
     * The maximum number of buffers in the pool.
     */
    private static int MAX_BUFFERS = 5;

    /**
     * The buffer pool.
     */
    private Vector pool = new Vector(MAX_BUFFERS);

    /**
     * Returns a buffer (byte array) of size BUFFER_SIZE from the
     * pool. When the buffer is no longer needed, it should be put back in the
     * pool for future use by calling putBuffer.
     *
     * @return a buffer
     * @see #putBuffer(byte[])
     */
    public synchronized byte[] getBuffer() {
        if (pool.isEmpty())
            return new byte[BUFFER_SIZE];
        byte[] buffer = (byte[]) pool.lastElement();
        pool.removeElementAt(pool.size() - 1);
        return buffer;
    }

    /**
     * Puts the given buffer into the pool for future use. The size of the
     * buffer must be BUFFER_SIZE.
     *
     * @param buffer the buffer to be put back into the buffer pool
     * @see #getBuffer()
     */
    public synchronized void putBuffer(byte[] buffer) {
        Assert.isNotNull(buffer);
        Assert.isTrue(buffer.length == BUFFER_SIZE);
        if (pool.size() < MAX_BUFFERS)
            pool.addElement(buffer);
    }
}


/*******************************************************************************
 * Copyright (c) 2008,2012 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are 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:
 *     IBM Corporation - Initial API and implementation
 *******************************************************************************/
package org.kie.eclipse.navigator.view;

import java.util.HashSet;
import java.util.Set;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.ui.actions.ActionContext;
import org.eclipse.ui.contexts.IContextService;
import org.eclipse.ui.forms.widgets.Form;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.navigator.CommonNavigator;
import org.eclipse.ui.navigator.CommonViewer;
import org.eclipse.ui.navigator.CommonViewerSiteFactory;
import org.eclipse.ui.navigator.ICommonViewerSite;
import org.eclipse.ui.navigator.NavigatorActionService;
import org.eclipse.ui.part.PageBook;
import org.eclipse.wst.server.core.IServer;
import org.eclipse.wst.server.core.IServerLifecycleListener;
import org.eclipse.wst.server.core.IServerListener;
import org.eclipse.wst.server.core.ServerCore;
import org.eclipse.wst.server.core.ServerEvent;
import org.kie.eclipse.navigator.KieNavigatorContentRoot;
import org.kie.eclipse.navigator.view.content.IContentNode;
import org.kie.eclipse.navigator.view.utils.ViewUtils;
import org.kie.eclipse.server.KieResourceHandler;
import org.osgi.service.prefs.BackingStoreException;
import org.osgi.service.prefs.Preferences;

/**
 * A view of servers, their modules, and status.
 */
public class KieNavigatorView extends CommonNavigator implements IKieNavigatorView, IResourceChangeListener {
	private static final String KIE_NAVIGATOR_VIEW_CONTEXT = "org.kie.eclipse.navigator.context";
	protected CommonViewer treeViewer;
	private Control mainPage;
	private Control noServersPage;
	PageBook book;

	protected IServerLifecycleListener serverResourceListener;
	protected IServerListener serverListener;

	// servers that are currently starting
	protected static Set<String> starting = new HashSet<String>(4);
	protected boolean animationActive = false;
	protected boolean stopAnimation = false;

	/**
	 * ServersView constructor comment.
	 */
	public KieNavigatorView() {
		super();
	}

	@Override
	protected Object getInitialInput() {
		KieNavigatorContentRoot root = new KieNavigatorContentRoot(this);
		return root;
	}

	@Override
	public void createPartControl(Composite parent) {
		// Add PageBook as parent composite
		FormToolkit toolkit = new FormToolkit(parent.getDisplay());
		book = new PageBook(parent, SWT.NONE);
		super.createPartControl(book);
		// Main page for the Servers tableViewer
		mainPage = getCommonViewer().getControl();
		// Page prompting to define a new server
		noServersPage = createDefaultPage(toolkit);
		book.showPage(mainPage);

		IContextService contextSupport = (IContextService) getSite().getService(IContextService.class);
		contextSupport.activateContext(KIE_NAVIGATOR_VIEW_CONTEXT);
		deferInitialization();
	}

	@Override
	protected CommonViewer createCommonViewerObject(Composite aParent) {
		return new CommonViewer(getViewSite().getId(), aParent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL) {
			@Override
			public ISelection getSelection() {
				return super.getSelection();
			}

			@Override
			protected void associate(Object element, Item item) {
				if (element instanceof IProject) {
					IProject project = (IProject) element;
					if (!project.exists() || !project.isOpen()) {
						Object data = item.getData("org.kie.navigator.content.node");
						if (data!=null)
							element = data;
					}
				}
				super.associate(element, item);
				if (element instanceof IContentNode) {
					item.setData("org.kie.navigator.content.node", element);
				}
			}

			@Override
			public ViewerComparator getComparator() {
				// The ContentNodes will handle sorting
				return null;
			}
		};
	}

	/**
	 * Creates a page displayed when there are no servers defined.
	 *
	 * @param kit
	 * @return Control
	 */
	private Control createDefaultPage(FormToolkit kit) {
		Form form = kit.createForm(book);
		Composite body = form.getBody();
		GridLayout layout = new GridLayout(2, false);
		body.setLayout(layout);

		Link hlink = new Link(body, SWT.NONE);
		hlink.setText("Use the Servers View to create a new server...");
		hlink.setBackground(book.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
		GridData gd = new GridData(SWT.LEFT, SWT.FILL, true, false);
		hlink.setLayoutData(gd);
		hlink.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				// show Servers View
				ViewUtils.showServersView();
			}
		});

		// Create the context menu for the default page
		final CommonViewer commonViewer = this.getCommonViewer();
		if (commonViewer != null) {
			ICommonViewerSite commonViewerSite = CommonViewerSiteFactory.createCommonViewerSite(this.getViewSite());

			if (commonViewerSite != null) {
				// Note: actionService cannot be null
				final NavigatorActionService actionService = new NavigatorActionService(commonViewerSite, commonViewer,
						commonViewer.getNavigatorContentService());

				MenuManager menuManager = new MenuManager("#PopupMenu");
				menuManager.addMenuListener(new IMenuListener() {
					public void menuAboutToShow(IMenuManager mgr) {
						ISelection selection = commonViewer.getSelection();
						actionService.setContext(new ActionContext(selection));
						actionService.fillContextMenu(mgr);
					}
				});
				Menu menu = menuManager.createContextMenu(body);

				// It is necessary to set the menu in two places:
				// 1. The white space in the server view
				// 2. The text and link in the server view. If this menu is not
				// set, if the
				// user right clicks on the text or uses shortcut keys to open
				// the context menu,
				// the context menu will not come up
				body.setMenu(menu);
				hlink.setMenu(menu);
			} else {
				// if (Trace.FINEST) {
				// Trace.trace(Trace.STRING_FINEST,
				// "The commonViewerSite is null");
				// }
			}
		} else {
			// if (Trace.FINEST) {
			// Trace.trace(Trace.STRING_FINEST, "The commonViewer is null");
			// }
		}

		return form;
	}

	/**
	 * Switch between the servers and default/empty page.
	 *
	 */
	void toggleDefaultPage() {
		if (treeViewer.getTree().getItemCount() < 1) {
			book.showPage(noServersPage);
		} else {
			book.showPage(mainPage);
		}
	}

	private void deferInitialization() {
		// TODO Angel Says: Need to do a final check on this line below. I don't
		// think there is anything else
		// that we need from to port from the old Servers View
		// initializeActions(getCommonViewer());

		Job job = new Job("Initializing Servers View") {
			public IStatus run(IProgressMonitor monitor) {
				IServer[] servers = ServerCore.getServers();
				int size = servers.length;
				for (int i = 0; i < size; i++) {
					((IServer) servers[i]).getModules();
				}
				deferredInitialize();
				return Status.OK_STATUS;
			}
		};

		job.setSystem(true);
		job.setPriority(Job.SHORT);
		job.schedule();
	}

	public void refresh() {
	}

	protected void deferredInitialize() {
		addListener();

		Display.getDefault().asyncExec(new Runnable() {
			public void run() {
				try {
					treeViewer = getCommonViewer();
					getSite().setSelectionProvider(treeViewer);

					// init the tooltip
					// ServerToolTip toolTip = new
					// ServerToolTip(tableViewer.getTree());
					// toolTip.setShift(new Point(10, 3));
					// toolTip.setPopupDelay(400); // in ms
					// toolTip.setHideOnMouseDown(true);
					// toolTip.activate();

				} catch (Exception e) {
					// ignore - view has already been closed
				}
			}
		});

		UpdateServerJob job = new UpdateServerJob(ServerCore.getServers());
		job.addJobChangeListener(new JobChangeAdapter() {
			@Override
			public void done(IJobChangeEvent event) {
				Display.getDefault().asyncExec(new Runnable() {
					public void run() {
						try {
							if (treeViewer.getTree().getItemCount() > 0) {
								Object obj = treeViewer.getTree().getItem(0).getData();
								treeViewer.setSelection(new StructuredSelection(obj));
							} else {
								toggleDefaultPage();
							}
						} catch (Exception e) {
							// if (Trace.WARNING) {
							// Trace.trace(Trace.STRING_WARNING,
							// "Failed to update the server view.", e);
							// }
						}
					}
				});
			}
		});
		job.schedule();
	}

	protected void refreshServerContent(final IServer server) {
		// if (Trace.FINEST) {
		// Trace.trace(Trace.STRING_FINEST, "Refreshing Content for server=" +
		// server);
		// }
		Display.getDefault().asyncExec(new Runnable() {
			public void run() {
				if (!treeViewer.getTree().isDisposed()) {
					Object[] expanded = treeViewer.getExpandedElements();
					treeViewer.refresh(server, true);
					treeViewer.setExpandedElements(expanded);
				}
			}
		});
	}

	protected void refreshServerState(final IServer server) {
		// if (Trace.FINEST) {
		// Trace.trace(Trace.STRING_FINEST, "Refreshing UI for server=" +
		// server);
		// }
		// ServerDecoratorsHandler.refresh(tableViewer);
	}

	@Override
	public void resourceChanged(final IResourceChangeEvent event) {
		Display.getDefault().asyncExec(new Runnable() {
			@Override
			public void run() {
				IResourceDelta delta = event.getDelta();
				if (delta!=null) {
					try {
						delta.accept(new IResourceDeltaVisitor() {

							@Override
							public boolean visit(IResourceDelta delta) throws CoreException {
								IResource resource = delta.getResource();
								if (resource instanceof IProject) {
									switch (delta.getKind()) {
									case IResourceDelta.ADDED:
									case IResourceDelta.REMOVED:
										KieNavigatorContentRoot root = (KieNavigatorContentRoot) treeViewer.getInput();
										root.getChildren();
										treeViewer.refresh(root, true);
										return false;
									}
								}
								return true;
							}

						});
					}
					catch (CoreException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		});
	}

	protected void addListener() {
		// To enable the UI updating of servers and its children
		serverResourceListener = new IServerLifecycleListener() {
			public void serverAdded(IServer server) {
				addServer(server);
				server.addServerListener(serverListener);
			}

			public void serverChanged(IServer server) {
				refreshServerContent(server);
			}

			public void serverRemoved(IServer server) {
				removeServer(server);
				server.removeServerListener(serverListener);
			}
		};
		ServerCore.addServerLifecycleListener(serverResourceListener);

		serverListener = new IServerListener() {
			public void serverChanged(ServerEvent event) {
				if (event == null)
					return;

				int eventKind = event.getKind();
				IServer server = event.getServer();
				if ((eventKind & ServerEvent.SERVER_CHANGE) != 0) {
					// server change event
					if ((eventKind & ServerEvent.STATE_CHANGE) != 0) {
						int state = event.getState();
						String id = server.getId();
						if (state == IServer.STATE_STARTING || state == IServer.STATE_STOPPING) {
							boolean startThread = false;
							synchronized (starting) {
								if (!starting.contains(id)) {
									if (starting.isEmpty())
										startThread = true;
									starting.add(id);
								}
							}
							if (startThread)
								startThread();
						} else {
							boolean stopThread = false;
							synchronized (starting) {
								if (starting.contains(id)) {
									starting.remove(id);
									if (starting.isEmpty())
										stopThread = true;
								}
							}
							if (stopThread)
								stopThread();
						}
						refreshServerState(server);
						refreshServerContent(server);
					} else if ((eventKind & ServerEvent.PUBLISH_STATE_CHANGE) != 0
							|| (eventKind & ServerEvent.STATUS_CHANGE) != 0) {
						refreshServerState(server);
					}

				} else if ((eventKind & ServerEvent.MODULE_CHANGE) != 0) {
					// module change event
					if ((eventKind & ServerEvent.STATE_CHANGE) != 0
							|| (eventKind & ServerEvent.PUBLISH_STATE_CHANGE) != 0
							|| (eventKind & ServerEvent.STATUS_CHANGE) != 0) {
						refreshServerContent(server);
					}
				}
			}
		};

		// add listeners to servers
		IServer[] servers = ServerCore.getServers();
		if (servers != null) {
			int size = servers.length;
			for (int i = 0; i < size; i++) {
				servers[i].addServerListener(serverListener);
			}
		}

		// add Resource listener to check for Project changes
        ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
	}

	protected void addServer(final IServer server) {
		Display.getDefault().asyncExec(new Runnable() {
			public void run() {
				KieNavigatorContentRoot root = new KieNavigatorContentRoot(KieNavigatorView.this);
				treeViewer.setInput(root);
				toggleDefaultPage();
			}
		});
	}

	protected void removeServer(final IServer server) {
		Display.getDefault().asyncExec(new Runnable() {
			public void run() {
				KieNavigatorContentRoot root = new KieNavigatorContentRoot(KieNavigatorView.this);
				treeViewer.setInput(root);
				toggleDefaultPage();
				KieResourceHandler.removeServerPreferences(server);
			}
		});
	}

	@Override
	public void dispose() {
		ServerCore.removeServerLifecycleListener(serverResourceListener);

		// remove listeners from servers
		IServer[] servers = ServerCore.getServers();
		if (servers != null) {
			int size = servers.length;
			for (int i = 0; i < size; i++) {
				servers[i].removeServerListener(serverListener);
			}
		}

		ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);

		super.dispose();
	}

	/**
	 * Start the animation thread
	 */
	protected void startThread() {
		if (animationActive)
			return;

		stopAnimation = false;

		final Display display = treeViewer == null ? Display.getDefault() : treeViewer.getControl().getDisplay();
		final int SLEEP = 200;
		final Runnable[] animator = new Runnable[1];
		animator[0] = new Runnable() {
			public void run() {
				if (!stopAnimation) {
					try {
						int size = 0;
						String[] servers;
						synchronized (starting) {
							size = starting.size();
							servers = new String[size];
							starting.toArray(servers);

						}

						for (int i = 0; i < size; i++) {
							IServer server = ServerCore.findServer(servers[i]);
							if (server != null) {
								// ServerDecorator.animate();
								treeViewer.update(server, new String[] { "ICON" });
							}
						}
					} catch (Exception e) {
						// if (Trace.FINEST) {
						// Trace.trace(Trace.STRING_FINEST,
						// "Error in Servers view animation", e);
						// }
					}
					display.timerExec(SLEEP, animator[0]);
				}
			}
		};
		Display.getDefault().asyncExec(new Runnable() {
			public void run() {
				display.timerExec(SLEEP, animator[0]);
			}
		});
	}

	protected void stopThread() {
		stopAnimation = true;
	}

	@Override
	public void refresh(Object element) {
		getCommonViewer().refresh(element);
	}

	@Override
	public void setProperty(String key, String value) {
		setPartProperty(key, value);
	}

	@Override
	public String getProperty(String key) {
		return getPartProperty(key);
	}
}


/*
 * 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.dom;

import java.util.Enumeration;
import java.util.NoSuchElementException;
import org.eclipse.webdav.Policy;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
 * An element editor for the WebDAV propertybehavior element. See
 * RFC2518 section 12.12 for the element's definition.
 *

 * 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 PropertyBehavior extends ElementEditor {
    /**
     * An ordered collection of the element names of the
     * propertybehavior element's children.
     */
    protected static final String[] childNames = new String[] {"omit", "keepalive"}; //$NON-NLS-1$ //$NON-NLS-2$

    /**
     * An ordered collection of the element names of the
     * propertybehavior element's children in the "omit" form
     */
    public static String[] fgNamesOmit = new String[] {"omit"}; //$NON-NLS-1$

    /**
     * An ordered collection of the element names of the
     * propertybehavior element's children in the "keep alive" form
     */
    public static String[] fgNamesKeepAlive = new String[] {"keepalive"}; //$NON-NLS-1$

    /**
     * Creates a new editor on the given WebDAV propertybehavior element.
     * The element is assumed to be well formed.
     *
     * @param root a propertybehavior element
     * @throws        MalformedElementException if there is reason to
     *                believe that the element is not well formed
     */
    public PropertyBehavior(Element root) throws MalformedElementException {
        super(root, "propertybehavior"); //$NON-NLS-1$
    }

    /**
     * Adds the given property href to this propertybehavior's list of live
     * properties. The property href must not be null and the
     * form of this property behavior must not already be omit or
     * keepAllAlive.
     *
     * @param propertyHref the property href to add
     */
    public void addProperty(String propertyHref) {
        Assert.isNotNull(propertyHref);
        Assert.isTrue(getFirstChild(root, "omit") == null); //$NON-NLS-1$
        Element keepalive = getFirstChild(root, "keepalive"); //$NON-NLS-1$
        if (keepalive == null)
            keepalive = addChild(root, "keepalive", fgNamesKeepAlive, true); //$NON-NLS-1$
        else
            Assert.isTrue(!"*".equals(getFirstText(keepalive))); //$NON-NLS-1$
        addChild(keepalive, "href", //$NON-NLS-1$
                encodeHref(propertyHref), new String[] {"href"}, //$NON-NLS-1$
                false);
    }

    /**
     * Creates a new WebDAV propertybehavior element and sets it as the root
     * of the given document. Returns an editor on the new propertybehavior
     * element. The document must not be null, and must not
     * already have a root element.
     *
     * @param document the document that will become the root of a new
     *                 propertybehavior element
     * @return         an element editor on a propertybehavior element
     */
    public static PropertyBehavior create(Document document) {
        Assert.isNotNull(document);
        Assert.isTrue(document.getOwnerDocument() == null);
        Element element = create(document, "propertybehavior"); //$NON-NLS-1$
        PropertyBehavior result = null;
        try {
            result = new PropertyBehavior(element);
        } catch (MalformedElementException e) {
            Assert.isTrue(false, Policy.bind("assert.internalError")); //$NON-NLS-1$
        }
        return result;
    }

    /**
     * Returns an Enumeration over this propertybehavior's
     * property hrefs. The methods isMerge() and
     * isKeepAllAlive return false if this propertybehavior is
     * in the "keep some alive" form.
     *
     * @return an Enumeration of Strings
     * @throws MalformedElementException if there is reason to believe that
     *         this editor's underlying element is not well formed, or this
     *         propertybehavior is not in the "keep some alive" form
     * @see    #isKeepAllAlive()
     * @see    #isOmit()
     */
    public Enumeration getProperties() throws MalformedElementException {

        Element keepalive = getFirstChild(root, "keepalive"); //$NON-NLS-1$
        ensureNotNull(Policy.bind("ensure.missingKeealiveElmt"), keepalive); //$NON-NLS-1$
        ensure(!"*".equals(getFirstText(keepalive)), //$NON-NLS-1$
                Policy.bind("ensure.wrongForm")); //$NON-NLS-1$

        final Element firstHref = getFirstChild(keepalive, "href"); //$NON-NLS-1$
        ensureNotNull(Policy.bind("ensure.missingHrefElmt"), firstHref); //$NON-NLS-1$

        Enumeration e = new Enumeration() {
            Element currentHref = firstHref;

            public boolean hasMoreElements() {
                return currentHref != null;
            }

            public Object nextElement() {
                if (!hasMoreElements())
                    throw new NoSuchElementException();
                String href = getFirstText(currentHref);
                currentHref = getTwin(currentHref, true);
                return decodeHref(href);
            }
        };

        return e;
    }

    /**
     * Returns true if this propertybehavior is in the
     * "keep all alive" form, otherwise, returns false.
     *
     * @return a boolean indicating whether this propertybehavior is in the
     *         "keep all alive" form or not
     * @throws MalformedElementException if there is reason to believe that
     *         this editor's underlying element is not well formed
     */
    public boolean isKeepAllAlive() throws MalformedElementException {
        Element child = getFirstChild(root, childNames);
        ensureNotNull(Policy.bind("ensure.expectingOmitOrKeepaliveElmt"), child); //$NON-NLS-1$
        boolean isKeepAllAlive = false;
        if (isDAVElement(child, "keepalive")) { //$NON-NLS-1$
            isKeepAllAlive = "*".equals(getFirstText(child)); //$NON-NLS-1$
            ensureNull(Policy.bind("ensure.conflictingHrefElmt"), getFirstChild(child, "href")); //$NON-NLS-1$ //$NON-NLS-2$
        }
        child = getNextSibling(child, childNames);
        ensureNull(Policy.bind("ensure.conflictingOmitOrKeepaliveElmt"), child); //$NON-NLS-1$
        return isKeepAllAlive;
    }

    /**
     * Returns true if this propertybehavior is in the
     * "omit" form, otherwise, returns false.
     *
     * @return a boolean indicating whether this propertybehavior is in the
     *         "omit" form or not
     * @throws MalformedElementException if there is reason to believe that
     *         this editor's underlying element is not well formed
     */
    public boolean isOmit() throws MalformedElementException {
        Element child = getFirstChild(root, childNames);
        ensureNotNull(Policy.bind("ensure.expectingOmitOrKeepaliveElmt"), child); //$NON-NLS-1$
        boolean isOmit = isDAVElement(child, "omit"); //$NON-NLS-1$
        child = getNextSibling(child, childNames);
        ensureNull(Policy.bind("ensure.conflictingOmitOrKeepaliveElmt"), child); //$NON-NLS-1$
        return isOmit;
    }

    /**
     * Sets whether this propertybehavior is in the "keep all alive" form or
     * not.
     *
     * @param isKeepAllAlive a boolean indicating whether this
     *                       propertybehavior will be in the "keep all
     *                       alive" form
     */
    public void setIsKeepAllAlive(boolean isKeepAllAlive) {
        Element child = getFirstChild(root, childNames);
        boolean isAlreadyKeepAllAlive = false;
        if (isDAVElement(child, "keepalive")) //$NON-NLS-1$
            isAlreadyKeepAllAlive = "*".equals(getFirstText(child)); //$NON-NLS-1$
        if (isKeepAllAlive) {
            if (!isAlreadyKeepAllAlive) {
                if (child != null)
                    root.removeChild(child);
                appendChild(root, "keepalive", "*"); //$NON-NLS-1$ //$NON-NLS-2$
            }
        } else if (isAlreadyKeepAllAlive)
            root.removeChild(child);
    }

    /**
     * Sets whether this propertybehavior is in the "omit" form or not.
     *
     * @param isOmit a boolean indicating whether this propertybehavior will
     *               be in the "omit" form
     */
    public void setIsOmit(boolean isOmit) {
        Element child = getFirstChild(root, childNames);
        boolean isAlreadyOmit = isDAVElement(child, "omit"); //$NON-NLS-1$
        if (isOmit) {
            if (!isAlreadyOmit) {
                if (child != null)
                    root.removeChild(child);
                appendChild(root, "omit"); //$NON-NLS-1$
            }
        } else if (isAlreadyOmit)
            root.removeChild(child);
    }
}


/*
 * 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.dom;

import java.util.Enumeration;
import java.util.NoSuchElementException;
import org.eclipse.webdav.IContext;
import org.eclipse.webdav.Policy;
import org.eclipse.webdav.internal.kernel.Context;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

/**
 * An element editor for the WebDAV activelock element. See RFC2518
 * section 12.1 for the element's definition.
 *

 * 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.
 *

 *
 * @see LockDiscovery
 * @see Owner
 */
public class ActiveLock extends ElementEditor {

    // An ordered collection of the element names of the activelock
    // element's children.
    protected static final String[] childNames = new String[] {"lockscope", //$NON-NLS-1$
            "locktype", //$NON-NLS-1$
            "depth", //$NON-NLS-1$
            "owner", //$NON-NLS-1$
            "timeout", //$NON-NLS-1$
            "locktoken"}; //$NON-NLS-1$

    /**
     * Creates a new editor on the given WebDAV activelock element. The
     * element is assumed to be well formed.
     *
     * @param root an activelock element
     * @throws        MalformedElementException if there is reason to
     *                believe that the element is not well formed
     */
    public ActiveLock(Element root) throws MalformedElementException {
        super(root, "activelock"); //$NON-NLS-1$
    }

    /**
     * Adds the given href to this activelock's locktoken. The href must not
     * be null.
     *
     * @param href the href to add
     */
    public void addLockTokenHref(String href) {
        Assert.isNotNull(href);
        Element locktoken = getLastChild(root, "locktoken"); //$NON-NLS-1$
        if (locktoken == null)
            locktoken = setChild(root, "locktoken", childNames, false); //$NON-NLS-1$
        appendChild(locktoken, "href", encodeHref(href)); //$NON-NLS-1$
    }

    /**
     * Returns the depth of this activelock; for example,
     * Context.DEPTH_ZERO.
     *
     * @throws MalformedElementException if there is reason to believe that
     *         this editor's underlying element is not well formed
     * @see    Context
     */
    public String getDepth() throws MalformedElementException {
        String depth = getChildText(root, "depth", false); //$NON-NLS-1$
        ensureNotNull(Policy.bind("ensure.missingDepthElmt"), depth); //$NON-NLS-1$
        ensure(depth.equals(IContext.DEPTH_ZERO) || depth.equals(IContext.DEPTH_ONE) || depth.equals(IContext.DEPTH_INFINITY), Policy.bind("ensure.invalidDepth", depth)); //$NON-NLS-1$
        return depth;
    }

    /**
     * Returns an Enumeration of Strings
     * containing this activelock's lock token hrefs.
     *
     * @return an Enumeration of Strings
     * @throws MalformedElementException if there is reason to believe that
     *         this editor's underlying element is not well formed
     */
    public Enumeration getLockTokenHrefs() throws MalformedElementException {
        Element locktoken = getLastChild(root, "locktoken"); //$NON-NLS-1$
        Element firstHref = null;
        if (locktoken != null) {
            firstHref = getFirstChild(locktoken, "href"); //$NON-NLS-1$
            ensureNotNull(Policy.bind("ensure.missingHrefElmt"), firstHref); //$NON-NLS-1$
        }
        final Node node = firstHref;
        Enumeration e = new Enumeration() {
            Node currentHref = node;

            public boolean hasMoreElements() {
                return currentHref != null;
            }

            public Object nextElement() {
                if (!hasMoreElements()) {
                    throw new NoSuchElementException();
                }
                String href = getFirstText((Element) currentHref);
                currentHref = getTwin((Element) currentHref, true);
                return decodeHref(href);
            }
        };

        return e;
    }

    /**
     * Returns this activelock's owner, or null if this
     * active lock has no owner.
     *
     * @return this activelock's owner, or null
     * @throws MalformedElementException if there is reason to believe that
     *         this editor's underlying element is not well formed
     */
    public Owner getOwner() throws MalformedElementException {
        Element owner = getLastChild(root, "owner"); //$NON-NLS-1$
        if (owner == null)
            return null;
        return new Owner(owner);
    }

    /**
     * Returns this activelock's timeout, or null if this
     * active lock has no timeout.
     *
     * @return this activelock's timeout, or null
     * @throws MalformedElementException if there is reason to believe that
     *         this editor's underlying element is not well formed
     */
    public String getTimeout() throws MalformedElementException {
        return getChildText(root, "timeout", false); //$NON-NLS-1$
    }

    /**
     * Returns true if this activelock is shared, or
     * false if it is exclusive.
     *
     * @return a boolean indicating whether this activelock is shared or
     *         exclusive
     * @throws MalformedElementException if there is reason to believe that
     *         this editor's underlying element is not well formed
     */
    public boolean isShared() throws MalformedElementException {

        Element lockscope = getFirstChild(root, "lockscope"); //$NON-NLS-1$
        ensureNotNull(Policy.bind("ensure.missingLockscopeElmt "), lockscope); //$NON-NLS-1$

        String[] names = new String[] {"shared", "exclusive"}; //$NON-NLS-1$ //$NON-NLS-2$
        Element sharedOrExclusive = getFirstChild(lockscope, names);
        ensureNotNull(Policy.bind("ensure.missingSharedOrExclusiveElmt"), sharedOrExclusive); //$NON-NLS-1$

        boolean isShared = isDAVElement(sharedOrExclusive, "shared"); //$NON-NLS-1$
        ensure(getNextSibling(sharedOrExclusive, names) == null, Policy.bind("ensure.conflictingSharedOrExclusiveElmt")); //$NON-NLS-1$

        return isShared;
    }

    /**
     * Sets the depth of this activelock to the given depth. The depth must
     * not be null and must be one of:
     *

     *
Context.DEPTH_ZERO
     *
Context.DEPTH_ONE
     *
Context.DEPTH_INFINITY
     *

     *
     * @param depth the depth for this activelock
     * @see         Context
     */
    public void setDepth(String depth) {
        Assert.isNotNull(depth);
        Assert.isTrue(depth.equals(IContext.DEPTH_ZERO) || depth.equals(IContext.DEPTH_ONE) || depth.equals(IContext.DEPTH_INFINITY));
        setChild(root, "depth", depth, childNames, false); //$NON-NLS-1$
    }

    /**
     * Sets whether this activelock is shared or exclusive. If isShared is
     * true, the activelock is set as shared, otherwise, the
     * activelock is set as exclusive.
     *
     * @param isShared a boolean indicating whether this activelock will be
     *                 set to be shared or exclusive
     */
    public void setIsShared(boolean isShared) {
        Element lockscope = setChild(root, "lockscope", childNames, true); //$NON-NLS-1$
        if (isShared)
            appendChild(lockscope, "shared"); //$NON-NLS-1$
        else
            appendChild(lockscope, "exclusive"); //$NON-NLS-1$
    }

    /**
     * Creates and sets an owner element on this activelock and returns an
     * editor on it.
     *
     * @return an editor on an owner element
     */
    public Owner setOwner() {
        Element owner = setChild(root, "owner", childNames, false); //$NON-NLS-1$
        Owner result = null;
        try {
            result = new Owner(owner);
        } catch (MalformedElementException e) {
            Assert.isTrue(false, Policy.bind("assert.internalError")); //$NON-NLS-1$
        }
        return result;
    }

    /**
     * Sets the timeout on this activelock to the given timeout. If the
     * timeout is null the current timeout is removed.
     *
     * @param timeout the timeout value for this activelock, or
     *                null for no timeout
     */
    public void setTimeout(String timeout) {
        if (timeout == null) {
            Element child = getLastChild(root, "timeout"); //$NON-NLS-1$
            if (child != null)
                root.removeChild(child);
        } else
            setChild(root, "timeout", timeout, childNames, false); //$NON-NLS-1$
    }
}


/*******************************************************************************
 * 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;

import java.util.List;

import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.wst.server.core.IServer;
import org.kie.eclipse.IKieConstants;
import org.osgi.service.prefs.Preferences;

import com.eclipsesource.json.JsonObject;
import com.eclipsesource.json.JsonValue;

/**
 *
 */
public abstract class KieResourceHandler implements IKieResourceHandler {

	protected static IEclipsePreferences preferences;
	protected IKieResourceHandler parent;
	protected List children;
	protected String name;
	protected JsonObject properties;

	public KieResourceHandler(IKieResourceHandler parent, String name) {
		this.parent = parent;
		this.name = name;
	}
	/* (non-Javadoc)
	 * @see org.kie.eclipse.navigator.view.server.IKieResourceHandler#getName()
	 */
	@Override
	public String getName() {
		return name;
	}

	@Override
	public IKieResourceHandler getParent() {
		return parent;
	}

	@Override
	public void setParent(IKieResourceHandler parent) {
		this.parent = parent;
	}

	@Override
	public IKieResourceHandler getRoot() {
		if (getParent()==null)
			return this;
		return getParent().getRoot();
	}

	@Override
	public Object getResource() {
		return null;
	}

	@Override
	public void setResource(Object resource) {
	}

	/* (non-Javadoc)
	 * @see org.kie.eclipse.navigator.view.server.IKieResourceHandler#getServer()
	 */
	@Override
	public IServer getServer() {
		if (parent!=null)
			return parent.getServer();
		return null;
	}

	@Override
	public String getRuntimeId() {
		if (parent!=null)
			return parent.getRuntimeId();
		return null;
    }

	@Override
	public IKieServiceDelegate getDelegate() {
		if (parent!=null)
			return parent.getDelegate();
		return null;
	}

	@Override
	public void dispose() {
		children = null;
	}

	@Override
	public Object load() {
		return null;
	}

	@Override
	public boolean isLoaded() {
		return false;
	}

	@Override
	public void setProperties(JsonObject properties) {
		JsonValue v = properties.get("name");
		if (v!=null && v.isString())
			name = v.asString();
		this.properties = properties;
	}

	@Override
	public JsonObject getProperties() {
		return properties;
	}

	public static void removeServerPreferences(IServer server) {
		try {
			String name = getCanonicalName(server.getName());
			IEclipsePreferences preferences = InstanceScope.INSTANCE.getNode(org.kie.eclipse.Activator.PLUGIN_ID);
			for (String key : preferences.keys()) {
				if (key.startsWith(name + IKieConstants.PREF_PATH_SEPARATOR)) {
					preferences.remove(key);
				}
			}
			preferences.flush();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	protected static String getCanonicalName(String name) {
		return name.replaceAll(IKieConstants.CANONICAL_NAME_PATTERN, IKieConstants.CANONICAL_NAME_REPLACEMENT);
	}

	/* (non-Javadoc)
	 * @see org.kie.eclipse.server.IKieResourceHandler#getPreferenceName(java.lang.String)
	 */
	@Override
	public String getPreferenceName(String name) {
		String canonicalName = getCanonicalName(getRoot().getName());
		if (name==null)
			return canonicalName;
		return canonicalName + IKieConstants.PREF_PATH_SEPARATOR + getCanonicalName(name);
	}

	public IPreferenceStore getPreferenceStore() {
		return org.kie.eclipse.Activator.getDefault().getPreferenceStore();
	}

	@Override
	public String getPreference(String name, String def) {
		if (getPreferenceStore().contains(getPreferenceName(name)))
			return getPreferenceStore().getString(getPreferenceName(name));
		return def;
	}

	@Override
	public boolean getPreference(String name, boolean def) {
		if (getPreferenceStore().contains(getPreferenceName(name)))
			return getPreferenceStore().getBoolean(getPreferenceName(name));
		return def;
	}

	@Override
	public int getPreference(String name, int def) {
		if (getPreferenceStore().contains(getPreferenceName(name)))
			return getPreferenceStore().getInt(getPreferenceName(name));
		return def;
	}

	@Override
	public void putPreference(String name, String value) {
		getPreferenceStore().putValue(getPreferenceName(name), value);
	}

	@Override
	public void putPreference(String name, boolean value) {
		getPreferenceStore().putValue(getPreferenceName(name), Boolean.toString(value));
	}

	@Override
	public void putPreference(String name, int value) {
		getPreferenceStore().putValue(getPreferenceName(name), Integer.toString(value));
	}
}


/*
 * 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.dom;

import org.eclipse.webdav.Policy;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
 * An element editor for the WebDAV lockinfo element. See RFC2518
 * section 12.6 for the element's definition.
 *

 * 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.
 *

 *
 * @see Owner
 */
public class LockInfo extends ElementEditor {
    /**
     * An ordered collection of the element names of the lockinfo
     * element's children.
     */
    public static final String[] childNames = new String[] {"lockscope", "locktype", "owner"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

    /**
     * Creates a new editor on the given WebDAV lockinfo element. The
     * element is assumed to be well formed.
     *
     * @param root a lockinfo element
     * @throws        MalformedElementException if there is reason to
     *                believe that the element is not well formed
     */
    public LockInfo(Element root) throws MalformedElementException {
        super(root, "lockinfo"); //$NON-NLS-1$
    }

    /**
     * Creates a new WebDAV lockinfo element and sets it as the root of the
     * given document. Returns an editor on the new lockinfo element. The
     * document must not be null, and must not already have a
     * root element.
     *
     * @param document the document that will become the root of a new
     *                 lockinfo element
     * @return         an element editor on a lockinfo element
     */
    public static LockInfo create(Document document) {
        Assert.isNotNull(document);
        Assert.isTrue(document.getOwnerDocument() == null);
        Element element = create(document, "lockinfo"); //$NON-NLS-1$
        Element locktype = appendChild(element, "locktype"); //$NON-NLS-1$
        appendChild(locktype, "write"); //$NON-NLS-1$
        LockInfo result = null;
        try {
            result = new LockInfo(element);
        } catch (MalformedElementException e) {
            Assert.isTrue(false, Policy.bind("assert.internalError")); //$NON-NLS-1$
        }
        return result;
    }

    /**
     * Returns this lockinfo's owner, or null if this lockinfo
     * has no owner.
     *
     * @return this lockinfo's owner, or null
     * @throws MalformedElementException if there is reason to believe that
     *         this editor's underlying element is not well formed
     */
    public Owner getOwner() throws MalformedElementException {
        Element owner = getLastChild(root, "owner"); //$NON-NLS-1$
        if (owner == null)
            return null;
        return new Owner(owner);
    }

    /**
     * Returns true if this lockinfo is shared and
     * false if it is exclusive.
     *
     * @return a boolean indicating whether this lockinfo is shared or
     *         exclusive
     * @throws MalformedElementException if there is reason to believe that
     *         this editor's underlying element is not well formed
     */
    public boolean isShared() throws MalformedElementException {
        Element lockscope = getFirstChild(root, "lockscope"); //$NON-NLS-1$
        ensureNotNull(Policy.bind("ensure.missingLockscopeElmt"), lockscope); //$NON-NLS-1$
        String[] names = new String[] {"shared", "exclusive"}; //$NON-NLS-1$ //$NON-NLS-2$
        Element sharedOrExclusive = getFirstChild(lockscope, names);
        ensureNotNull(Policy.bind("ensure.missingSharedOrExclusiveElmt"), sharedOrExclusive); //$NON-NLS-1$
        boolean isShared = isDAVElement(sharedOrExclusive, "shared"); //$NON-NLS-1$
        ensure(getNextSibling(sharedOrExclusive, names) == null, Policy.bind("ensure.conflictingSharedOrExclusiveElmt")); //$NON-NLS-1$
        return isShared;
    }

    /**
     * Sets whether this lockinfo is shared or exclusive. If isShared is
     * true, the lockinfo is set as shared, otherwise, the
     * lockinfo is set as exclusive.
     *
     * @param isShared a boolean indicating whether this lockinfo will be
     *                 set to be shared or exclusive
     */
    public void setIsShared(boolean isShared) {
        Element lockscope = setChild(root, "lockscope", childNames, true); //$NON-NLS-1$
        if (isShared)
            appendChild(lockscope, "shared"); //$NON-NLS-1$
        else
            appendChild(lockscope, "exclusive"); //$NON-NLS-1$
    }

    /**
     * Sets the owner on this lockinfo and returns an editor on it.
     */
    public Owner setOwner() {
        Element owner = setChild(root, "owner", childNames, false); //$NON-NLS-1$
        Owner result = null;
        try {
            result = new Owner(owner);
        } catch (MalformedElementException e) {
            Assert.isTrue(false, Policy.bind("assert.internalError")); //$NON-NLS-1$
        }
        return result;
    }
}


/*
 * 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 java.util.Enumeration;
import java.util.Vector;
import org.eclipse.webdav.IResponse;

/**
 * A ConditionTerm represents some state configuration 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. ConditionTerms are contained in a Condition which is used in the Precondition
 * of a WebDAV If header.
 */
public class ConditionTerm {

    private Vector conditionFactors = new Vector();

    /**
     * Construct a Condition with no associated Resource URI.
     */
    public ConditionTerm() {
        super();
    }

    /**
     * Add a ConditionFactor to a ConditionTerm.
     *
     * @param factor the factor to add
     * @exception WebDAVException thrown if the term already contains the factor
     */
    public void addConditionFactor(ConditionFactor factor) throws WebDAVException {
        if (conditionFactors.contains(factor))
            throw new WebDAVException(IResponse.SC_BAD_REQUEST, Policy.bind("error.parseDuplicateEntry")); //$NON-NLS-1$
        conditionFactors.addElement(factor);
    }

    /**
     * Does this ConditionTerm contain the given ConditionFactor?
     *
     * @param factor the factor to check for
     * @return true if the term contains the given factor
     */
    public boolean contains(ConditionFactor factor) {
        return conditionFactors.contains(factor);
    }

    /**
     * Create a ConditionTerm by parsing the given If header as defined by
     * section 9.4 in the WebDAV spec.
     *
     * @param tokenizer a StreamTokenizer on the contents of a WebDAV If header
     * @return the parsed ConditionTerm
     * @exception WebDAVException thrown if there is a syntax error in the If header
     */
    public static ConditionTerm create(StreamTokenizer tokenizer) throws WebDAVException {
        ConditionTerm term = new ConditionTerm();
        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$

            while (token == StreamTokenizer.TT_WORD || token == '<' || token == '[') {
                term.addConditionFactor(ConditionFactor.create(tokenizer));
                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$
        } catch (IOException exc) {
            // ignore or log?
        }
        if (!term.getConditionFactors().hasMoreElements())
            throw new WebDAVException(IResponse.SC_BAD_REQUEST, Policy.bind("error.parseMissingStateOrEntity")); //$NON-NLS-1$
        return term;
    }

    /**
     * Get all the ConditionFactors in this Condition. The ConditionFactors in
     * a Condition must all match with states of the resource, i.e., they are AND'ed
     * together. ConditionTerms are contained in a Condition which is used in the
     * Precondition of a WebDAV If header.
     *
     * @return an Enumeration of ConditionFactors
     */
    public Enumeration getConditionFactors() {
        return conditionFactors.elements();
    }

    /**
     * See if this ConditionTerm matches the given ConditionTerm. This is an
     * AND operation. All the factors in the ConditionTerm must match.
     *
     * @param conditionTerm the term to match
     * @return true if all the factors in the term match those in this term
     */
    public boolean matches(ConditionTerm conditionTerm) {
        int numberOfItemsToMatch = 0;
        boolean match = true;
        Enumeration factors = getConditionFactors();
        while (match && factors.hasMoreElements()) {
            ConditionFactor factor = (ConditionFactor) factors.nextElement();
            if (factor.not()) {
                match = !conditionTerm.contains(factor);
            } else {
                match = conditionTerm.contains(factor);
                numberOfItemsToMatch++;
            }
        }
        match = match && numberOfItemsToMatch == conditionTerm.numberOfFactors();
        return match;
    }

    /**
     * Get the number of ConditionFactors in this ConditionTerm.
     *
     * @return the number of factors in this term
     */
    public int numberOfFactors() {
        return conditionFactors.size();
    }

    /**
     * Return a String representation of this ConditionTerm as defined by section 9.4
     * of the WebDAV Spec.
     *
     * @return a string representation of this term
     */
    public String toString() {
        StringBuffer buffer = new StringBuffer();
        buffer.append('(');
        Enumeration factors = getConditionFactors();
        while (factors.hasMoreElements()) {
            ConditionFactor factor = (ConditionFactor) factors.nextElement();
            buffer.append(factor.toString());
            if (factors.hasMoreElements())
                buffer.append(' ');
        }
        buffer.append(')');
        return buffer.toString();
    }
}


/*
 * 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.dsl.editor;

import org.drools.eclipse.dsl.editor.completion.DSLRuleCompletionProcessor;
import org.drools.eclipse.editors.DRLSourceViewerConfig;
import org.drools.eclipse.editors.completion.DefaultCompletionProcessor;
import org.drools.eclipse.editors.scanners.DRLPartionScanner;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.contentassist.ContentAssistant;
import org.eclipse.jface.text.contentassist.IContentAssistant;
import org.eclipse.jface.text.source.ISourceViewer;

/**
 * Source viewer config wires up the syntax highlighting, partitioning
 * and content assistance.
 */
public class DSLRuleSourceViewerConfig extends DRLSourceViewerConfig {

    public DSLRuleSourceViewerConfig(DSLRuleEditor editor) {
        super(editor);
    }

    /**
     * Get the appropriate content assistance, for each partition.
     */
    public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) {
        ContentAssistant assistant = new ContentAssistant();
        assistant.setContentAssistProcessor(
            new DefaultCompletionProcessor(getEditor()), IDocument.DEFAULT_CONTENT_TYPE);
        assistant.setContentAssistProcessor(
            new DSLRuleCompletionProcessor(getEditor()), DRLPartionScanner.RULE_PART_CONTENT);
        assistant.setProposalPopupOrientation(IContentAssistant.PROPOSAL_OVERLAY);
        assistant.setAutoActivationDelay(0);
        return assistant;
    }
}


/*
 * 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.part;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;

import org.drools.eclipse.editors.rete.figure.VertexFigure;
import org.drools.eclipse.editors.rete.model.Connection;
import org.drools.eclipse.editors.rete.model.GraphicalVertex;
import org.drools.eclipse.editors.rete.model.ModelElement;
import org.drools.eclipse.editors.rete.model.VertexPropertySource;
import org.drools.eclipse.reteoo.BaseVertex;
import org.eclipse.draw2d.ConnectionAnchor;
import org.eclipse.draw2d.EllipseAnchor;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.ConnectionEditPart;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
import org.eclipse.ui.views.properties.IPropertySource;

/**
 * EditPart used for Vertices
 */
class VertexEditPart extends AbstractGraphicalEditPart
    implements
    PropertyChangeListener,
    org.eclipse.gef.NodeEditPart {

    private IPropertySource  propertySource;

    private ConnectionAnchor anchor;

    /* (non-Javadoc)
     * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#activate()
     */
    public void activate() {
        if ( !isActive() ) {
            super.activate();
            ((ModelElement) getModel()).addPropertyChangeListener( this );
            propertySource = new VertexPropertySource( getCastedModel() );
        }
    }

    /* (non-Javadoc)
     * @see org.eclipse.gef.editparts.AbstractEditPart#createEditPolicies()
     */
    protected void createEditPolicies() {
    }

    /*(non-Javadoc)
     * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#createFigure()
     */
    protected IFigure createFigure() {
        return new VertexFigure( getCastedModel().getFillColor(),
                                 getCastedModel().getDrawColor() );
    }

    /* (non-Javadoc)
     * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#deactivate()
     */
    public void deactivate() {
        if ( isActive() ) {
            super.deactivate();
            ((ModelElement) getModel()).removePropertyChangeListener( this );
            propertySource = null;
        }
    }

    private BaseVertex getCastedModel() {
        return (BaseVertex) getModel();
    }

    private ConnectionAnchor getConnectionAnchor() {
        if ( anchor == null ) {
            if ( getModel() instanceof BaseVertex ) anchor = new EllipseAnchor( getFigure() );
            else
            // if Nodes gets extended the conditions above must be updated
            throw new IllegalArgumentException( "unexpected model" );
        }
        return anchor;
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#getModelSourceConnections()
     */
    protected List<Connection> getModelSourceConnections() {
        return getCastedModel().getSourceConnections();
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#getModelTargetConnections()
     */
    protected List<Connection> getModelTargetConnections() {
        return getCastedModel().getTargetConnections();
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.gef.NodeEditPart#getSourceConnectionAnchor(org.eclipse.gef.ConnectionEditPart)
     */
    public ConnectionAnchor getSourceConnectionAnchor(ConnectionEditPart connection) {
        return getConnectionAnchor();
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.gef.NodeEditPart#getSourceConnectionAnchor(org.eclipse.gef.Request)
     */
    public ConnectionAnchor getSourceConnectionAnchor(Request request) {
        return getConnectionAnchor();
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.gef.NodeEditPart#getTargetConnectionAnchor(org.eclipse.gef.ConnectionEditPart)
     */
    public ConnectionAnchor getTargetConnectionAnchor(ConnectionEditPart connection) {
        return getConnectionAnchor();
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.gef.NodeEditPart#getTargetConnectionAnchor(org.eclipse.gef.Request)
     */
    public ConnectionAnchor getTargetConnectionAnchor(Request request) {
        return getConnectionAnchor();
    }

    /* (non-Javadoc)
     * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
     */
    public void propertyChange(PropertyChangeEvent evt) {
        String prop = evt.getPropertyName();
        if ( GraphicalVertex.SIZE_PROP.equals( prop ) || GraphicalVertex.LOCATION_PROP.equals( prop ) ) {
            refreshVisuals();
        } else if ( GraphicalVertex.SOURCE_CONNECTIONS_PROP.equals( prop ) ) {
            refreshSourceConnections();
        } else if ( GraphicalVertex.TARGET_CONNECTIONS_PROP.equals( prop ) ) {
            refreshTargetConnections();
        }
    }

    /* (non-Javadoc)
     * @see org.eclipse.gef.editparts.AbstractEditPart#refreshVisuals()
     */
    protected void refreshVisuals() {
        Rectangle bounds = new Rectangle( getCastedModel().getLocation(),
                                          getCastedModel().getSize() );
        ((GraphicalEditPart) getParent()).setLayoutConstraint( this,
                                                               getFigure(),
                                                               bounds );
    }

    /* (non-Javadoc)
     * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#getAdapter(java.lang.Class)
     */
    public Object getAdapter(@SuppressWarnings("rawtypes") Class key) {
        if ( key == IPropertySource.class ) {
            return propertySource;
        }
        return super.getAdapter( key );
    }

}