/*-
 * #%L
 * Nazgul Project: nazgul-tools-validation-api
 * %%
 * Copyright (C) 2010 - 2018 jGuru Europe AB
 * %%
 * Licensed under the jGuru Europe AB license (the "License"), based
 * on Apache License, Version 2.0; you may not use this file except
 * in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *       http://www.jguru.se/licenses/jguruCorporateSourceLicense-2.0.txt
 *
 * 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.
 * #L%
 */

package se.jguru.nazgul.tools.validation.api.expression;

import se.jguru.nazgul.tools.validation.api.exception.AbstractErrorMessageContainer;
import se.jguru.nazgul.tools.validation.api.exception.ErrorMessageContainer;

import java.util.Collection;
import java.util.Map;

/**
 * Builder class producing ValidationExpressions.
 * It is recommended for all users of this class to perform a static import,
 * in order for the DSL to become more fluent.
 *
 * @author Lennart Jörelid, jGuru Europe AB
 */
public class ExpressionBuilder implements ValidationExecutor {

    // Internal state
    private final ErrorMessageContainer messageContainer;

    /**
     * Creates a new ExpressionBuilder, using the provided Exception as
     * container for any built messages.
     *
     * @param messageContainer The InternalStateValidationException to use
     *                         as container for all messages created by any
     *                         chained ValidationExpression instances managed
     *                         by this ExpressionBuilder.
     * @throws IllegalArgumentException if the messageContainer instance was null.
     */
    public ExpressionBuilder(final ErrorMessageContainer messageContainer) throws IllegalArgumentException {

        // Check sanity
        if(messageContainer == null) {
            throw new NullPointerException("Cannot handle null 'messageContainer' argument.");
        }

        // Assign internal state
        this.messageContainer = messageContainer;
    }

    /**
     * Ends this (chain of) ValidationExpressions and performs the actual validation.
     *
     * @throws AbstractErrorMessageContainer if the aggregate ValidationExpression failed to validate correctly.
     */
    @Override
    public void endExpressionAndValidate() throws AbstractErrorMessageContainer {
        messageContainer.endExpressionAndValidate();
    }

    /**
     * Adds an arbitrary description.
     *
     * @param desc The description to add.
     * @return This object.
     */
    public ExpressionBuilder addDescription(final String desc) {
        messageContainer.addErrorMessage(desc);
        return this;
    }

    /**
     * Adds a description for a null property.
     *
     * @param property The property to check.
     * @param name     The property name.
     * @return This object.
     */
    public ExpressionBuilder notNull(final Object property, final String name) {

        if (property == null) {
            messageContainer.addErrorMessage("Property '" + name + "' cannot be null");
        }

        return this;
    }

    /**
     * Adds a description for a property, if the provided expression is not true.
     *
     * @param expression The expression to check.
     * @param name       The expression name.
     * @return This object.
     */
    public ExpressionBuilder notTrue(final boolean expression, final String name) {

        if (expression) {
            messageContainer.addErrorMessage("Expression '" + name + "' cannot be true.");
        }

        return this;
    }

    /**
     * Adds a description for a null or empty property (Strings, Collections and Maps are
     * checked for emptyness as well as null-ness).
     *
     * @param property The property to check.
     * @param name     The property name.
     * @return This object.
     */
    public ExpressionBuilder notNullOrEmpty(final Object property, final String name) {

        notNull(property, name);

        if (property instanceof String && ((String) property).isEmpty()) {
            messageContainer.addErrorMessage("Property '" + name + "' cannot be empty.");
        }
        if (property instanceof Collection && ((Collection<?>) property).isEmpty()) {
            messageContainer.addErrorMessage("Collection '" + name + "' must contain elements.");
        }
        if (property instanceof Map && ((Map<?, ?>) property).isEmpty()) {
            messageContainer.addErrorMessage("Map '" + name + "' must contain elements.");
        }

        return this;
    }
}


/*
 * Icegem, Extensions library for VMWare vFabric GemFire
 *
 * Copyright (c) 2010-2011, Grid Dynamics Consulting Services Inc. or third-party
 * contributors as indicated by the @author tags or express copyright attribution
 * statements applied by the authors.
 *
 * This copyrighted material is made available to anyone wishing to use, modify,
 * copy, or redistribute it subject to the terms and conditions of the GNU
 * Lesser General Public License v3, as published by the Free Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * You should have received a copy of the GNU Lesser General Public License v3
 * along with this distribution; if not, write to:
 * Free Software Foundation, Inc.
 * 51 Franklin Street, Fifth Floor
 * Boston, MA  02110-1301  USA
 */
package com.googlecode.icegem.cacheutils;

import java.util.Arrays;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;

import com.googlecode.icegem.cacheutils.common.Utils;
import com.googlecode.icegem.cacheutils.comparator.CompareTool;
import com.googlecode.icegem.cacheutils.monitor.MonitorTool;
import com.googlecode.icegem.cacheutils.replication.CheckReplicationTool;
import com.googlecode.icegem.cacheutils.signallistener.WaitforTool;
import com.googlecode.icegem.cacheutils.updater.UpdateTool;

/**
 * Aggregates cache utilities and handles the common options.
 */
public class Launcher {
    /** */
    private static final String DEBUG_OPTION = "debug";

    /** */
    private static final String QUIET_OPTION = "quiet";

    /** */
    private static final String HELP_OPTION = "help";

    /** */
    private static final boolean DEFAULT_DEBUG_ENABLED = false;

    /** */
    private static final boolean DEFAULT_QUIET = false;

    /** */
    private static boolean debugEnabled = DEFAULT_DEBUG_ENABLED;

    /** */
    private static boolean quiet = DEFAULT_QUIET;

    /**
     * Represents the utility.
     */
    private enum Command {
	/** */
	COMPARE("compare", new CompareTool()),

	/** */
	MONITOR("monitor", new MonitorTool()),

	/** */
	CHECK_REPLICATION("check-replication", new CheckReplicationTool()),

	/** */
	UPDATE("update", new UpdateTool()),

	/** */
	WAITFOR("waitfor", new WaitforTool());

	/** Command name. */
	private String name;

	/** Command executable. */
	private Executable exec;

	/**
	 * @param name Command name.
	 * @param exec Command executable.
	 */
	private Command(String name, Executable exec) {
	    this.name = name;
	    this.exec = exec;
	}

	/**
	 * @return Command name.
	 */
	public String getName() {
	    return name;
	}

	/**
	 * @return Command executable.
	 */
	public Executable getExec() {
	    return exec;
	}

	/**
	 * Gets tool by name.
	 *
	 * @param commandName
	 *            - The name of the command.
	 * @return - found tool or null if the utility is not found.
	 */
	public static Executable getUtil(String commandName) {
	    Executable result = null;

	    for (Command command : Command.values()) {
		if (command.getName().equals(commandName.trim())) {
		    result = command.getExec();

		    break;
		}
	    }

	    return result;
	}
    }

    /**
     * Prints help and exits.
     */
    private static void printHelp() {
	Options options = constructGnuOptions();

	printHelp(options);
    }

    /**
     * Parses command line arguments.
     *
     * @param commandLineArguments
     *            - The arguments.
     */
    private static void parseCommandLineArguments(String[] commandLineArguments) {
	Options options = constructGnuOptions();

	CommandLineParser parser = new GnuParser();

	try {
	    CommandLine line = parser.parse(options, commandLineArguments);

	    if (line.hasOption(HELP_OPTION)) {
		printHelp(options);
	    }

	    if (line.hasOption(DEBUG_OPTION)) {
		debugEnabled = true;
	    }

	    if (!debugEnabled && line.hasOption(QUIET_OPTION)) {
		quiet = true;
	    }
	} catch (Throwable t) {
	    printHelp(options);
	}
    }

    /**
     * Prints help if requested.
     *
     * @param options
     *            - The GNU options.
     */
    private static void printHelp(final Options options) {
	StringBuilder sb = new StringBuilder();

	sb.append("java -jar icegem-cache-utils-<version>.jar [options] <");

	Command[] commands = Command.values();

	for (int i = 0; i < commands.length; i++) {
	    sb.append(commands[i].getName());

	    if (i < (commands.length - 1)) {
		sb.append(" | ");
	    }
	}

	sb.append("> [command_specific_options]");

	HelpFormatter formatter = new HelpFormatter();

	formatter.printHelp(sb.toString(), options);

	Utils.exitWithFailure();
    }

    /**
     * Constructs the set of GNU options.
     *
     * @return - The constructed options.
     */
    private static Options constructGnuOptions() {
	final Options gnuOptions = new Options();

	gnuOptions.addOption("d", DEBUG_OPTION, false, "Print debug information")
		.addOption("q", QUIET_OPTION, false, "Quiet output. Doesn't work if --" + DEBUG_OPTION + " specified.")
		.addOption("h", HELP_OPTION, false, "Print usage information");

	return gnuOptions;
    }

    /**
     * Looks for the index of command in the specified array.
     *
     * @param args
     *            - Arguments.
     * @return - Index of command, or -1 if command is not found in the array.
     */
    private static int findCommandIndex(String[] args) {
	int commandIndex = -1;

	for (int i = 0; i < args.length; i++) {
	    for (Command command : Command.values()) {
		if (command.getName().equals(args[i].trim())) {
		    commandIndex = i;

		    break;
		}
	    }
	}

	return commandIndex;
    }

    /**
     * Extracts the launcher arguments from the all arguments array.
     *
     * @param args
     *            - All arguments.
     * @param commandIndex
     *            - Index of the command.
     * @return - Launcher arguments.
     */
    private static String[] extractLauncherArgs(String[] args, int commandIndex) {
	String[] launcherArgs = new String[commandIndex];

	System.arraycopy(args, 0, launcherArgs, 0, commandIndex);

	return launcherArgs;
    }

    /**
     * Extracts the command-specific arguments from the all arguments array.
     *
     * @param args
     *            - All arguments.
     * @param commandIndex
     *            - Index of the command.
     * @return - Command-specific arguments.
     */
    private static String[] extractCommandArgs(String[] args, int commandIndex) {
	String[] commandArgs = new String[args.length - commandIndex - 1];

	System.arraycopy(args, commandIndex + 1, commandArgs, 0, args.length - commandIndex - 1);

	return commandArgs;
    }

    /**
     * The entry point of the application.
     *
     * @param args
     *            - All arguments.
     * @throws Exception
     */
    public static void main(String[] args) {
	try {
	    int commandIndex = findCommandIndex(args);

	    if (commandIndex < 0) {
		printHelp();
	    }

	    String[] launcherArgs = extractLauncherArgs(args, commandIndex);
	    String[] commandArgs = extractCommandArgs(args, commandIndex);

	    parseCommandLineArguments(launcherArgs);

	    debug("Launcher#main(): args = " + Arrays.asList(args));
	    debug("Launcher#main(): launcherArgs = " + Arrays.asList(launcherArgs));
	    debug("Launcher#main(): commandArgs = " + Arrays.asList(commandArgs));

	    String commandName = args[commandIndex];

	    Executable tool = Command.getUtil(commandName);

	    if (tool != null) {
		tool.execute(commandArgs, debugEnabled, quiet);
	    } else {
		debug("Launcher#main(): Command \"" + commandName + "\" not found");

		printHelp();
	    }
	} catch (Throwable t) {
	    debug("Launcher#main(): Throwable caught with message = " + t.getMessage(), t);

	    Utils.exitWithFailure("Unexpected throwable", t);
	}
    }

    /**
     * Prints debug information if debug is enabled.
     *
     * @param message
     *            - Debug message.
     */
    private static void debug(String message) {
	debug(message, null);
    }

    /**
     * Prints debug information if debug is enabled.
     *
     * @param message
     *            - Debug message.
     * @param t
     *            - Instance of Throwable.
     */
    private static void debug(String message, Throwable t) {
	if (debugEnabled) {
	    System.err.println("0 [Launcher] " + message);

	    if (t != null) {
		t.printStackTrace(System.err);
	    }
	}
    }
}


/*-
 * #%L
 * Nazgul Project: nazgul-tools-visualization-api
 * %%
 * Copyright (C) 2010 - 2018 jGuru Europe AB
 * %%
 * Licensed under the jGuru Europe AB license (the "License"), based
 * on Apache License, Version 2.0; you may not use this file except
 * in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *       http://www.jguru.se/licenses/jguruCorporateSourceLicense-2.0.txt
 *
 * 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.
 * #L%
 */

package se.jguru.nazgul.tools.visualization.api.dot;

import se.jguru.nazgul.tools.visualization.api.AbstractStringRenderer;
import se.jguru.nazgul.tools.visualization.api.RenderConfiguration;
import se.jguru.nazgul.tools.visualization.model.diagram.statement.Edge;
import se.jguru.nazgul.tools.visualization.model.diagram.statement.RightSideEdge;

/**
 * Edge statement Renderer, complying to the specification in the
 * DOT language specification.
 *
 * @author Lennart Jörelid, jGuru Europe AB
 */
public class EdgeRenderer extends AbstractStringRenderer<Edge> {

    // Internal state
    private AttributeRenderer attributeRenderer;
    private NodeIdRenderer nodeIdRenderer;
    private RightSideEdgeRenderer rightSideEdgeRenderer;

    /**
     * Default constructor.
     */
    public EdgeRenderer() {

        // Delegate
        super(Edge.class);

        // Assign internal state
        attributeRenderer = new AttributeRenderer();
        nodeIdRenderer = new NodeIdRenderer();
        rightSideEdgeRenderer = new RightSideEdgeRenderer();
    }

    /**
     *
Renders the supplied Edge according to the following structure:

     *
(node_id | subgraph) edgeRHS [ attr_list ]

     *
... where ...

     *
edgeRHS   : edgeop (node_id | subgraph) [ edgeRHS ]

     *
     * @param config The non-null RenderConfiguration.
     * @param edge   The non-null Edge to be rendered.
     */
    @Override
    protected String doRender(final RenderConfiguration config, final Edge edge) {

        // Edges can be from/to Nodes and Subgraphs. Pick the correct ID source.
        final String edgeID = edge.getNodeID() != null
                ? nodeIdRenderer.doRender(config, edge.getNodeID())
                : quote(edge.getSubgraph().getId());

        // Render the attributes after the RightSideEdge.
        final RightSideEdge rightSideEdge = edge.getRightSideEdge();
        return config.getIndent() + edgeID + " "
                + rightSideEdgeRenderer.doRender(config, rightSideEdge) + " "
                + attributeRenderer.doRender(config, edge.getAttributes());
    }
}


/*
 * Icegem, Extensions library for VMWare vFabric GemFire
 *
 * Copyright (c) 2010-2011, Grid Dynamics Consulting Services Inc. or third-party
 * contributors as indicated by the @author tags or express copyright attribution
 * statements applied by the authors.
 *
 * This copyrighted material is made available to anyone wishing to use, modify,
 * copy, or redistribute it subject to the terms and conditions of the GNU
 * Lesser General Public License v3, as published by the Free Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * You should have received a copy of the GNU Lesser General Public License v3
 * along with this distribution; if not, write to:
 * Free Software Foundation, Inc.
 * 51 Franklin Street, Fifth Floor
 * Boston, MA  02110-1301  USA
 */
package com.googlecode.icegem.cacheutils.monitor;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import javax.mail.MessagingException;

import com.googlecode.icegem.utils.PropertiesHelper;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.log4j.Logger;

import com.googlecode.icegem.cacheutils.Tool;
import com.googlecode.icegem.cacheutils.common.Utils;
import com.googlecode.icegem.cacheutils.monitor.controller.NodesController;
import com.googlecode.icegem.cacheutils.monitor.controller.event.NodeEventHandler;
import com.googlecode.icegem.cacheutils.monitor.utils.EmailService;

/**
 * Periodically checks the distributed system status and sends mail in case of
 * failure
 */
public class MonitorTool extends Tool {
	private static final String HELP_OPTION = "help";

	private static final String TIMEOUT_OPTION = "timeout";

	private static final String PERIOD_OPTION = "period";

	private static final String LOCATORS_OPTION = "locators";

	private static final String ALL_OPTION = "all";

	private static final String SERVER_OPTION = "server";

	private static final Logger log = Logger.getLogger(MonitorTool.class);

	private static final long DEFAULT_TIMEOUT = 3000;

	private static final long DEFAULT_PERIOD = 10000;

	private boolean allOption;
	private String serverHostOption;
	private int serverPortOption;
	private long timeout = DEFAULT_TIMEOUT;
	private long period = DEFAULT_PERIOD;
	private String locators = null;

	private NodesController nodesController;
	private PropertiesHelper propertiesHelper;
	private Timer timer;

	private List<NodeEventHandler> customEventHandlersList = new ArrayList<NodeEventHandler>();

	/**
	 * Periodically running task which checks the system status
	 */
	private class IsAliveTimerTask extends TimerTask {

		@Override
		public void run() {
			try {
				nodesController.update();
			} catch (Throwable t) {
				log.error(Utils.currentDate() + "  Throwable caught", t);
				t.printStackTrace();
				try {
					EmailService
						.getInstance()
						.send(
							propertiesHelper
								.getStringProperty("icegem.cacheutils.monitor.email.exception.subject"),
							propertiesHelper
								.getStringProperty(
									"icegem.cacheutils.monitor.email.exception.content",
									t.getMessage(), new Date()));
				} catch (MessagingException me) {
					me.printStackTrace();
				}
			}

		}

	}

	/**
	 * configuration
	 * */
	private void init() {
		try {
			log.info(Utils.currentDate() + "");
			log.info(Utils.currentDate()
				+ "  --------------------------------------------------");
			log.info(Utils.currentDate() + "  Monitoring tool started");
			log.info(Utils.currentDate()
				+ "  --------------------------------------------------");

			propertiesHelper = new PropertiesHelper("/monitoring.properties");

			nodesController = new NodesController(propertiesHelper, locators,
				timeout);

			nodesController.addNodeEventHandler(new LoggerNodeEventHandler());

			for (NodeEventHandler handler : customEventHandlersList) {
				nodesController.addNodeEventHandler(handler);
			}

			timer = new Timer();
		} catch (Throwable t) {
			Utils.exitWithFailure("Throwable caught during the initialization",
				t);
		}
	}

	/**
	 * Starts the checking task
	 */
	private void start() {
		try {
			timer.schedule(new IsAliveTimerTask(), 0, period);
		} catch (Throwable t) {
			Utils.exitWithFailure("Throwable caught during the startup", t);
		}
	}

	public void shutdown() {
		nodesController.shutdown();

		timer.cancel();
		timer = null;
	}

	public static boolean isServerAlive(String host, int port, long timeout) {
		boolean serverAlive = false;

		try {
			PropertiesHelper propertiesHelper = new PropertiesHelper(
				"/monitoring.properties");

			NodesController nodesController = new NodesController(
				propertiesHelper, null, timeout);

			serverAlive = nodesController.isServerAlive(host, port);

			nodesController.shutdown();
		} catch (Throwable t) {
			Utils.exitWithFailure(
				"Throwable caught during the check if the server alive", t);
		}

		return serverAlive;
	}

	public void addNodeEventHandler(NodeEventHandler handler) {
		customEventHandlersList.add(handler);
	}

	public void execute(String[] args, boolean debugEnabled, boolean quiet) {
		try {
			parseCommandLineArguments(args);

			if (serverHostOption != null) {
				boolean serverAlive = MonitorTool.isServerAlive(
					serverHostOption, serverPortOption, timeout);

				if (serverAlive) {
					System.out.println("alive");
					Utils.exitWithSuccess();
				}

				System.out.println("down");
				Utils.exitWithFailure();
			} else if (allOption) {
				init();
				start();
			} else {
				Utils
					.exitWithFailure("Cannot determine the mode of application");
			}
		} catch (Throwable t) {
			Utils.exitWithFailure("Unexpected throwable", t);
		}
	}

	protected void parseCommandLineArguments(String[] commandLineArguments) {
		Options options = constructGnuOptions();

		if (commandLineArguments.length < 1) {
			printHelp(options);
		}

		try {
			CommandLineParser parser = new GnuParser();
			CommandLine line = parser.parse(options, commandLineArguments);

			if (line.hasOption(HELP_OPTION)) {
				printHelp(options);
			}

			if (line.hasOption(TIMEOUT_OPTION)) {
				timeout = Long.parseLong(line.getOptionValue(TIMEOUT_OPTION));
			}

			if (line.hasOption(PERIOD_OPTION)) {
				period = Long.parseLong(line.getOptionValue(PERIOD_OPTION));
			}

			boolean allOptionTemp = line.hasOption(ALL_OPTION);
			String serverOptionTemp = line.getOptionValue(SERVER_OPTION);

			if (serverOptionTemp != null) {
				int indexOfPortStart = serverOptionTemp.indexOf('[');
				int indexOfPortEnd = serverOptionTemp.indexOf(']');
				serverHostOption = serverOptionTemp.substring(0,
					indexOfPortStart);
				String portString = serverOptionTemp.substring(
					indexOfPortStart + 1, indexOfPortEnd);
				serverPortOption = Integer.parseInt(portString);
			} else if (allOptionTemp) {
				allOption = allOptionTemp;

				if (line.hasOption(LOCATORS_OPTION)) {
					locators = line.getOptionValue(LOCATORS_OPTION);
				} else {
					Utils.exitWithFailure("The option --" + LOCATORS_OPTION
						+ " should be used when the option --" + ALL_OPTION
						+ " specified");
				}
			} else {
				Utils.exitWithFailure("The option --" + SERVER_OPTION
					+ " or --" + ALL_OPTION + " should be specified");
			}

		} catch (Throwable t) {
			Utils
				.exitWithFailure(
					"Throwable caught during the command-line arguments parsing",
					t);
		}
	}

	protected void printHelp(final Options options) {
		HelpFormatter formatter = new HelpFormatter();
		formatter.printHelp("monitor <--" + HELP_OPTION + " | --"
			+ SERVER_OPTION + " [--" + TIMEOUT_OPTION + "] | --" + ALL_OPTION
			+ " <--" + LOCATORS_OPTION + "> [--" + PERIOD_OPTION + "] [--"
			+ TIMEOUT_OPTION + "] >", options);

		Utils.exitWithFailure();
	}

	protected Options constructGnuOptions() {
		final Options gnuOptions = new Options();

		gnuOptions
			.addOption(
				"s",
				SERVER_OPTION,
				true,
				"Check one server and exit with status 0 if server alive, or with status 1 if server is dead or down. Server should be in format host[port].")
			.addOption(
				"a",
				ALL_OPTION,
				false,
				"Periodically check all the servers related to locators specified in monitoring.properties file")
			.addOption("l", LOCATORS_OPTION, true,
				"List of locators in format host1[port1],host2[port2]")
			.addOption("p", PERIOD_OPTION, true,
				"Period between runs, ms. Default value is " + DEFAULT_PERIOD)
			.addOption("t", TIMEOUT_OPTION, true,
				"Timeout, ms. Default value is " + DEFAULT_TIMEOUT)
			.addOption("h", HELP_OPTION, false, "Print usage information");

		return gnuOptions;

	}

}


/*
 * Icegem, Extensions library for VMWare vFabric GemFire
 *
 * Copyright (c) 2010-2011, Grid Dynamics Consulting Services Inc. or third-party
 * contributors as indicated by the @author tags or express copyright attribution
 * statements applied by the authors.
 *
 * This copyrighted material is made available to anyone wishing to use, modify,
 * copy, or redistribute it subject to the terms and conditions of the GNU
 * Lesser General Public License v3, as published by the Free Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * You should have received a copy of the GNU Lesser General Public License v3
 * along with this distribution; if not, write to:
 * Free Software Foundation, Inc.
 * 51 Franklin Street, Fifth Floor
 * Boston, MA  02110-1301  USA
 */
package com.googlecode.icegem.cacheutils.common;

import java.io.InvalidClassException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javassist.CannotCompileException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.type.filter.AnnotationTypeFilter;

import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.client.ClientCache;
import com.gemstone.gemfire.cache.client.ClientCacheFactory;
import com.gemstone.gemfire.cache.client.ClientRegionFactory;
import com.gemstone.gemfire.cache.client.ClientRegionShortcut;
import com.googlecode.icegem.serialization.AutoSerializable;
import com.googlecode.icegem.serialization.HierarchyRegistry;

/**
 * TODO: Create appropriate javadoc.
 *
 * Connects to distributed system as client in order to perform some tasks on a certain regions.
 */
public class PeerCacheService {
    /** */
    private static final Logger log = LoggerFactory.getLogger(PeerCacheService.class);

    /** */
    private ClientCache cache;

    /** */
    private List<String> scanPackages = new ArrayList<String>();

    /** */
    private ClientRegionFactory proxyRegionFactory;

    /**
     * @param serverOptionsString
     * @param scanPackages
     * @throws Exception
     */
    public PeerCacheService(String serverOptionsString, List<String> scanPackages) throws Exception {
	if (scanPackages != null) {
	    this.scanPackages = scanPackages;

	    registerSerializers();
	}

	ClientCacheFactory clientCacheFactory = new ClientCacheFactory();

	String[] serverOptions = serverOptionsString.split(",");

	for (String serverOption : serverOptions) {
	    if (serverOption != null) {
		String serverHost = serverOption.substring(0, serverOption.indexOf("["));
		String serverPort = serverOption.substring(serverOption.indexOf("[") + 1, serverOption.indexOf("]"));

		clientCacheFactory.addPoolServer(serverHost, Integer.parseInt(serverPort));
	    }
	}

	clientCacheFactory.set("log-level", "none");

	this.cache = clientCacheFactory.create();
    }

    /**
     * Creates regions structure similar to server region structure.
     *
     * @param regionNames names of the regions to reconstruct.
     * @return set of created regions.
     */
    public Set<Region<?, ?>> createRegions(Map<String, String> regionNames) {
	Set<Region<?, ?>> regions = new HashSet<Region<?, ?>>();

	proxyRegionFactory = cache.createClientRegionFactory(ClientRegionShortcut.PROXY);

	for (String regionPath : regionNames.keySet()) {
	    Region region = createRegion(regionPath, regionNames.get(regionPath));

	    regions.add(region);
	}

	return regions;
    }

    /**
     * @param regionNames Region names represented by mapping {regionPath => regionName}.
     * @return Region.
     */
    public Region<?, ?> createRegion(Map<String, String> regionNames) {
	proxyRegionFactory = cache.createClientRegionFactory(ClientRegionShortcut.PROXY);

	Region region = null;

	for (Map.Entry<String, String> e : regionNames.entrySet()) {
	    region = createRegion(e.getKey(), e.getValue());
	}

	return region;
    }

    /**
     * @param regionPath
     * @param regionName
     * @return
     */
    private Region<?, ?> createRegion(String regionPath, String regionName) {
	Region region = null;

	if (regionPath.equals("/" + regionName)) {
	    region = proxyRegionFactory.create(regionName);
	} else {
	    Region parentRegion = cache.getRegion(regionPath.substring(0, regionPath.lastIndexOf("/" + regionName)));

	    if (parentRegion != null)
		region = parentRegion.createSubregion(regionName, parentRegion.getAttributes());
	}

	return region;
    }

    /**
     *
     */
    public void close() {
	cache.close();
    }

    /**
     * @throws Exception
     */
    private void registerSerializers() throws Exception {
	ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

	registerClasses(classLoader);
    }

    /**
     * @param classLoader
     * @throws Exception
     */
    private void registerClasses(ClassLoader classLoader) throws Exception {
	List<Class<?>> classesFromPackages = new ArrayList<Class<?>>();

	for (String pack : scanPackages) {
	    log.info("Scan package " + pack + " for classes marked by @AutoSerializable");

	    ClassPathScanningCandidateComponentProvider ppp = new ClassPathScanningCandidateComponentProvider(false);

	    ppp.addIncludeFilter(new AnnotationTypeFilter(AutoSerializable.class));

	    Set<BeanDefinition> candidateComponents = ppp.findCandidateComponents(pack);

	    for (BeanDefinition beanDefinition : candidateComponents) {
		String className = beanDefinition.getBeanClassName();

		final Class<?> clazz = Class.forName(className);

		classesFromPackages.add(clazz);
	    }
	}

	try {
	    HierarchyRegistry.registerAll(classLoader, classesFromPackages);
	} catch (InvalidClassException e) {
	    final String msg = "Some class from list " + classesFromPackages + " is nor serializable. Cause: "
		    + e.getMessage();

	    log.error(msg);

	    throw new RuntimeException(msg, e);
	} catch (CannotCompileException e) {
	    final String msg = "Can't compile DataSerializer classes for some classes from list " + classesFromPackages
		    + ". Cause: " + e.getMessage();

	    log.error(msg);

	    throw new RuntimeException(msg, e);
	}
    }
}


/*-
 * #%L
 * Nazgul Project: nazgul-tools-visualization-api
 * %%
 * Copyright (C) 2010 - 2018 jGuru Europe AB
 * %%
 * Licensed under the jGuru Europe AB license (the "License"), based
 * on Apache License, Version 2.0; you may not use this file except
 * in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *       http://www.jguru.se/licenses/jguruCorporateSourceLicense-2.0.txt
 *
 * 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.
 * #L%
 */

package se.jguru.nazgul.tools.visualization.api.dot;

import se.jguru.nazgul.tools.visualization.api.AbstractStringRenderer;
import se.jguru.nazgul.tools.visualization.api.RenderConfiguration;
import se.jguru.nazgul.tools.visualization.model.diagram.Comment;

import java.util.List;

/**
 * AbstractStringRenderer implementation for rendering Comments,
 * using either C-style single-line '//' or multiple-line delimiters,
 * depending on how many lines were added to the Comments being rendered.
 *
 * @author Lennart Jörelid, jGuru Europe AB
 */
public class CommentRenderer extends AbstractStringRenderer<Comment> {

    /**
     * Default constructor.
     */
    public CommentRenderer() {
        super(Comment.class);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected String doRender(final RenderConfiguration config, final Comment comment) {

        // Check sanity
        final StringBuilder builder = new StringBuilder(config.getNewline() + config.getIndent());
        final List<String> commentLines = comment.getCommentLines();

        if (commentLines.size() == 1) {

            // Use a '//' single-line comment
            builder.append("// ").append(commentLines.get(0));

        } else if (commentLines.size() > 1) {

            // Use a '/*' ... '*/' multi-line comment
            builder.append("/* ").append(config.getNewline());
            for (String current : commentLines) {
                builder.append(config.getIndent()).append(" * ").append(current).append(config.getNewline());
            }
            builder.append(config.getIndent()).append(" */");
        }

        // All Done.
        return builder.toString() + config.getNewline();
    }
}


/*
 * Icegem, Extensions library for VMWare vFabric GemFire
 *
 * Copyright (c) 2010-2011, Grid Dynamics Consulting Services Inc. or third-party
 * contributors as indicated by the @author tags or express copyright attribution
 * statements applied by the authors.
 *
 * This copyrighted material is made available to anyone wishing to use, modify,
 * copy, or redistribute it subject to the terms and conditions of the GNU
 * Lesser General Public License v3, as published by the Free Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * You should have received a copy of the GNU Lesser General Public License v3
 * along with this distribution; if not, write to:
 * Free Software Foundation, Inc.
 * 51 Franklin Street, Fifth Floor
 * Boston, MA  02110-1301  USA
 */
package com.googlecode.icegem.expiration;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.execute.FunctionService;

/**
 *

 * The class which can expire region entries using custom policy (strategy).
 *

 *
 *

 * Example:
 *
 *

 *
 * Region<Long, Data> dataRegion = ...;
 * Region<Long, Error> errorsRegion = ...;
 *
 * ExpirationController expirationController = new ExpirationController();
 *
 * long destroyedEntriesNumberForData = expirationController.process(dataRegion,
 * 	new ExpirationPolicy() {
 *
 * 		public boolean isExpired(Entry<Object, Object> entry) {
 * 			// TODO: Add some logic
 * 			return false;
 * 		}
 * 	});
 *
 * long destroyedEntriesNumberForErrors = expirationController.process(errorsRegion,
 * 	new ExpirationPolicy() {
 *
 * 		public boolean isExpired(Entry<Object, Object> entry) {
 * 			// TODO: Add some logic
 * 			return false;
 * 		}
 * 	});
 *
 *

 *
 *

 *
 *

 * You can get access to the other regions inside of
 * isExpired(Entry<Object, Object>) method in the following
 * way:
 *
 *

 * new ExpirationPolicy() {
 *
 *   public boolean isExpired(Entry<Object, Object> entry) {
 *     RegionService regionService = entry.getRegion().getRegionService();
 *     Region<Long, TransactionProcessingError> errorsRegion = regionService.getRegion("errors");
 *
 *     // TODO: Add some logic
 *     return false;
 *   }
 * });
 *

 *
 *

 *
 */
public class ExpirationController {

	private Logger logger = LoggerFactory.getLogger(ExpirationController.class);

	private static final long DEFAULT_PACKET_SIZE = 1;
	private static final long DEFAULT_PACKET_DELAY = 0;

	private long packetSize = DEFAULT_PACKET_SIZE;
	private long packetDelay = DEFAULT_PACKET_DELAY;

	/**
	 * Gets the size of the consistently expired entries packet
	 *
	 * @return - the packet size
	 */
	public long getPacketSize() {
		return packetSize;
	}

	/**
	 * Gets the size of the consistently expired entries packet
	 *
	 * @param packetSize
	 *            - the packet size
	 */
	public void setPacketSize(long packetSize) {
		this.packetSize = packetSize;
	}

	/**
	 * Gets the delay in processing after the packetSize entries, milliseconds
	 *
	 * @return - the packet delay
	 */
	public long getPacketDelay() {
		return packetDelay;
	}

	/**
	 * Sets the delay in processing after the packetSize entries, milliseconds
	 *
	 * @param packetDelay
	 *            - the packet delay
	 */
	public void setPacketDelay(long packetDelay) {
		this.packetDelay = packetDelay;
	}

	/**
	 * Applies the specified policy on the specified region and returns number
	 * of destroyed entries.
	 *
	 * @param region
	 *            - the region
	 * @param policy
	 *            - the expiration policy
	 * @return - the number of destroyed region entries
	 */
	public long process(Region<?, ?> region, ExpirationPolicy policy) {

		long destroyedEntriesNumber = 0;

		try {

			if (region == null) {
				throw new IllegalStateException("The Region cannot be null");
			}

			if (policy == null) {
				throw new IllegalArgumentException(
					"The ExpirationPolicy cannot be null");
			}

			logger
				.info("Running ExpirationController process with parameters region = "
					+ region
					+ ", policy = "
					+ policy
					+ ", packetSize = "
					+ packetSize + ", packetDelay = " + packetDelay);

			DestroyedEntriesCountCollector collector = (DestroyedEntriesCountCollector) FunctionService
				.onRegion(region)
				.withArgs(
					new ExpirationFunctionArguments(packetSize, packetDelay))
				.withCollector(new DestroyedEntriesCountCollector())
				.execute(new ExpirationFunction(policy));

			Object result = collector.getResult();
			if (result instanceof Long) {
				destroyedEntriesNumber = (Long) result;
			}

			logger
				.info("ExpirationController process with parameters region = "
					+ region + ", policy = " + policy + ", packetSize = "
					+ packetSize + ", packetDelay = " + packetDelay
					+ " has destroyed " + destroyedEntriesNumber + " entries");

		} catch (RuntimeException re) {
			logger.error("RuntimeException during processing", re);
			throw re;
		}

		return destroyedEntriesNumber;
	}
}


/*-
 * #%L
 * Nazgul Project: nazgul-tools-visualization-api
 * %%
 * Copyright (C) 2010 - 2018 jGuru Europe AB
 * %%
 * Licensed under the jGuru Europe AB license (the "License"), based
 * on Apache License, Version 2.0; you may not use this file except
 * in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *       http://www.jguru.se/licenses/jguruCorporateSourceLicense-2.0.txt
 *
 * 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.
 * #L%
 */

package se.jguru.nazgul.tools.visualization.api;

import java.io.Serializable;
import java.util.Map;
import java.util.TreeMap;

/**
 * Configuration holder for properties affecting rendering.
 *
 * @author Lennart Jörelid, jGuru Europe AB
 * @see Renderer
 */
public class RenderConfiguration implements Serializable {

    /**
     * OS-neutral newline String/char.
     */
    public static final String NEWLINE = System.getProperty("line.separator");

    /**
     * A default indentation string, holding 2 whitespaces.
     */
    public static final String TWO_SPACES = "  ";

    // Internal state
    private Map<String, Object> extraConfiguration;
    private int indentationLevel;
    private String indentationToken;
    private boolean isDirectedGraph;

    /**
     * Default constructor creating a RenderConfiguration using indentationLevel 0
     * and two spaces for indentationToken (i.e. {@link #TWO_SPACES}).
     */
    public RenderConfiguration() {
        this(0);
    }

    /**
     * Convenience constructor creating a RenderConfiguration with the supplied indentation level and using two
     * spaces for indentationToken (i.e. {@link #TWO_SPACES}).
     *
     * @param indentationLevel The non-negative indentation level.
     */
    public RenderConfiguration(final int indentationLevel) {
        this(indentationLevel, TWO_SPACES, true);
    }

    /**
     * Compound constructor creating a RenderConfiguration wrapping the supplied data.
     *
     * @param indentationLevel The non-negative indentation level.
     * @param indentationToken The non-empty and non-null indentation token.
     * @param isDirectedGraph  {@code true} to indicate that a directed graph should be rendered.
     */
    public RenderConfiguration(final int indentationLevel,
                               final String indentationToken,
                               final boolean isDirectedGraph) {

        // Assign internal state
        this.extraConfiguration = new TreeMap<>();
        setIndentationLevel(indentationLevel);
        setIndentationToken(indentationToken);
        setDirectedGraph(isDirectedGraph);
    }

    /**
     * @return true if this RenderConfiguration is used within a Directed Graph.
     */
    public boolean isDirectedGraph() {
        return isDirectedGraph;
    }

    /**
     * Assigns true or false to the {@link #isDirectedGraph} property.
     *
     * @param directedGraph true if this RenderConfiguration is used within a Directed Graph.
     */
    public void setDirectedGraph(final boolean directedGraph) {
        isDirectedGraph = directedGraph;
    }

    /**
     * Assigns the active indentationLevel for this RenderConfiguration.
     *
     * @param indentationLevel the active indentationLevel for this RenderConfiguration. Cannot be negative.
     */
    public final void setIndentationLevel(final int indentationLevel) {

        // Check sanity
        if (indentationLevel < 0) {
            throw new IllegalArgumentException("Cannot handle 'indentationLevel' < 0. Got: " + indentationLevel);
        }

        // Assign internal state
        this.indentationLevel = indentationLevel;
    }

    /**
     * Assigns the indentationToken of this RenderConfiguration.
     *
     * @param indentationToken the indentationToken of this RenderConfiguration. Cannot be null or empty.
     */
    public final void setIndentationToken(final String indentationToken) {

        // Check sanity
        if (indentationToken == null || indentationToken.isEmpty()) {
            throw new IllegalArgumentException("Cannot handle null or empty 'indentationToken' argument.");
        }

        // Assign internal state
        this.indentationToken = indentationToken;
    }

    /**
     * Clones this RenderConfiguration, and changes the indentation level (of the returned
     * RenderConfiguration) as indicated.
     *
     * @param indentationChange The change of the indentation level in the returned RenderConfiguration.
     * @return A {@link RenderConfiguration} clone of this one - except that the indentationLevel is changed with the
     * supplied amount.
     * @throws IllegalArgumentException if the indentationLevel after the change is negative.
     * @see #setIndentationLevel(int)
     */
    public final RenderConfiguration cloneAndChangeIndentation(final int indentationChange)
            throws IllegalArgumentException {

        // Check sanity
        final int newIndentationLevel = getIndentationLevel() + indentationChange;
        final RenderConfiguration toReturn = new RenderConfiguration(
                newIndentationLevel,
                indentationToken,
                isDirectedGraph);

        toReturn.getExtraConfiguration().putAll(getExtraConfiguration());

        // All Done.
        return toReturn;
    }

    /**
     * Retrieves a full indent, given the {@link #indentationToken} and {@link #indentationLevel}.
     *
     * @return The full string to be emitted before a properly indented token is rendered.
     */
    public String getIndent() {

        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < getIndentationLevel(); i++) {
            builder.append(indentationToken);
        }

        // All Done.
        return builder.toString();
    }

    /**
     * Convenience method to retrieve the {@link #NEWLINE}
     *
     * @return {@link #NEWLINE}
     */
    public String getNewline() {
        return NEWLINE;
    }

    /**
     * Retrieves the Map containing extra configuration for rendering.
     *
     * @return the non-null Map containing extra configuration for rendering.
     */
    public Map<String, Object> getExtraConfiguration() {
        return extraConfiguration;
    }

    /**
     * Retrieves the (non-negative) indentation level of this RenderConfiguration.
     *
     * @return the non-negative indentation level of this RenderConfiguration.
     */
    public int getIndentationLevel() {
        return indentationLevel;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString() {
        return "RenderConfiguration: "
                + NEWLINE + " indentationLevel   : " + indentationLevel
                + NEWLINE + " indentationToken   : '" + indentationToken + "'"
                + NEWLINE + " extraConfiguration : " + extraConfiguration;
    }
}


/*
 * #%L
 * Nazgul Project: nazgul-tools-codestyle
 * %%
 * Copyright (C) 2010 - 2015 jGuru Europe AB
 * %%
 * Licensed under the jGuru Europe AB license (the "License"), based
 * on Apache License, Version 2.0; you may not use this file except
 * in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *        http://www.jguru.se/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.
 * #L%
 */
package se.jguru.nazgul.tools.codestyle.enforcer.rules.source;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileReader;
import java.io.IOException;
import java.util.regex.Pattern;

/**
 * Java-flavoured PackageExtractor implementation, validating performance over
 * complete (i.e. AST) correctness.
 *
 * @author Lennart Jörelid, jGuru Europe AB
 */
public class JavaPackageExtractor implements PackageExtractor {

    /**
     * The 'package' reserved Java word.
     */
    public static final String PACKAGE_WORD = "package";

    /**
     * Regular expression to search for a package statement line.
     * Does not perform full Java AST construction of the source file given - instead
     * preferring parsing speed.
     */
    public static final Pattern PACKAGE_STATEMENT = Pattern.compile(
            "^\\s*" + PACKAGE_WORD + "\\s*([a-zA-Z_][a-zA-Z0-9_]*(\\.[a-zA-Z_][a-zA-Z0-9_]*)*)?\\s*;\\s*$");

    /**
     * FileFilter which identifies a normal Java source file.
     */
    public static final FileFilter JAVA_SOURCE_FILEFILTER = new FileFilter() {
        @Override
        public boolean accept(final File aFile) {
            return aFile != null
                    && (aFile.isFile() && aFile.getName().toLowerCase().trim().endsWith(".java"));
        }
    };

    /**
     * Retrieves the package definition from the supplied sourceFile.
     *
     * @param sourceFile The sourceFile from which the package definition should be extracted.
     * @return The package of the sourceFile.
     */
    @Override
    public String getPackage(final File sourceFile) {

        String aLine = getPackage(sourceFile, PACKAGE_STATEMENT);
        if (aLine != null) return aLine;

        // No package statement found.
        // Return default package.
        return "";
    }

    static String getPackage(final File sourceFile, final Pattern packageStatement) {
        try (BufferedReader bufferedReader = new BufferedReader(new FileReader(sourceFile))) {

            String aLine;
            while ((aLine = bufferedReader.readLine()) != null) {

                if (packageStatement.matcher(aLine.trim()).matches()) {
                    return aLine.substring(
                            aLine.indexOf(PACKAGE_WORD) + PACKAGE_WORD.length(), aLine.indexOf(";"))
                            .trim();
                }
            }
        } catch (IOException e) {
            throw new IllegalArgumentException("Could not determine package from file ["
                    + sourceFile.getAbsolutePath() + "]. Not a Java file?", e);
        }
        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public FileFilter getSourceFileFilter() {
        return JAVA_SOURCE_FILEFILTER;
    }
}


/*-
 * #%L
 * Nazgul Project: nazgul-tools-visualization-spi-doclet
 * %%
 * Copyright (C) 2010 - 2018 jGuru Europe AB
 * %%
 * Licensed under the jGuru Europe AB license (the "License"), based
 * on Apache License, Version 2.0; you may not use this file except
 * in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *       http://www.jguru.se/licenses/jguruCorporateSourceLicense-2.0.txt
 *
 * 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.
 * #L%
 */

package se.jguru.nazgul.tools.visualization.spi.doclet.javadoc;

import com.sun.javadoc.DocErrorReporter;
import com.sun.javadoc.LanguageVersion;
import com.sun.javadoc.RootDoc;
import com.sun.tools.doclets.standard.Standard;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * This is a doclet drafted simply to investigate the Doclet Lifecycle.
 * The Doclet documentation is itself quite lacking in clarity and detail.
 * It is simply too difficult to set up proper unit tests for Doclets.
 *
 * @author Lennart Jörelid, jGuru Europe AB
 */
public class LifecycleInvestigationDoclet {

    // Internal state
    private static List<String> eventSequence = new ArrayList<>();

    /**
     * Generate documentation here.
     * This method is required for all doclets.
     *
     * @return true on success.
     */
    public static boolean start(final RootDoc root) {

        // Perform some reflective investigation of the RootDoc

        final boolean toReturn = Standard.start(root);
        eventSequence.add("start (root): " + toReturn);

        // We should emit the eventSequence here.
        for(int i = 0; i < eventSequence.size(); i++) {
            System.out.println(" event [" + i + " / " + eventSequence.size() + "]: " + eventSequence.get(i));
        }

        // All Done.
        return toReturn;
    }

    /**
     *
Check for doclet-added options.  Returns the number of
     * arguments you must specify on the command line for the
     * given option.  For example, "-d docs" would return 2.

     *
This method is required if the doclet contains any options.
     * If this method is missing, Javadoc will print an invalid flag
     * error for every option.

     *
     * @return number of arguments on the command line for an option
     * including the option name itself.  Zero return means
     * option not known.  Negative value means error occurred.
     */
    public static int optionLength(final String option) {

        final int standardOptionLength = Standard.optionLength(option);

        eventSequence.add("optionLength (" + option + "): " + standardOptionLength);

        return standardOptionLength;
    }

    /**
     * Check that options have the correct arguments.
     *

     * This method is not required, but is recommended,
     * as every option will be considered valid if this method
     * is not present.  It will default gracefully (to true)
     * if absent.
     *

     * Printing option related error messages (using the provided
     * DocErrorReporter) is the responsibility of this method.
     *
     * @return true if the options are valid.
     */
    public static boolean validOptions(final String options[][], DocErrorReporter reporter) {

        final boolean toReturn = Standard.validOptions(options, reporter);

        if(options == null || options.length == 0) {
            eventSequence.add("validOptions (none supplied): " + toReturn);
        } else{
            for (int i = 0; i < options.length; i++) {

                final String thisOption = Arrays.stream(options[i]).reduce((l, r) -> l + " " + r).orElse("<none>");
                eventSequence.add("validOptions [" + i + " / " + options.length + "] (" + thisOption + "): " + toReturn);
            }
        }

        // All Done.
        return toReturn;
    }

    /**
     * Return the version of the Java Programming Language supported
     * by this doclet.
     *

     * This method is required by any doclet supporting a language version
     * newer than 1.1.
     *
     * @return the language version supported by this doclet.
     * @since 1.5
     */
    public static LanguageVersion languageVersion() {
        return LanguageVersion.JAVA_1_5;
    }
}


/*
 * Icegem, Extensions library for VMWare vFabric GemFire
 *
 * Copyright (c) 2010-2011, Grid Dynamics Consulting Services Inc. or third-party
 * contributors as indicated by the @author tags or express copyright attribution
 * statements applied by the authors.
 *
 * This copyrighted material is made available to anyone wishing to use, modify,
 * copy, or redistribute it subject to the terms and conditions of the GNU
 * Lesser General Public License v3, as published by the Free Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * You should have received a copy of the GNU Lesser General Public License v3
 * along with this distribution; if not, write to:
 * Free Software Foundation, Inc.
 * 51 Franklin Street, Fifth Floor
 * Boston, MA  02110-1301  USA
 */
package com.googlecode.icegem.cacheutils.monitor.controller;

import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.mail.MessagingException;

import com.gemstone.gemfire.admin.AdminException;
import com.gemstone.gemfire.admin.OperationCancelledException;
import com.gemstone.gemfire.admin.SystemMember;
import com.gemstone.gemfire.admin.SystemMemberCache;
import com.gemstone.gemfire.admin.SystemMemberCacheServer;
import com.gemstone.gemfire.cache.client.Pool;
import com.gemstone.gemfire.cache.client.PoolFactory;
import com.gemstone.gemfire.cache.client.PoolManager;
import com.googlecode.icegem.cacheutils.common.AdminService;
import com.googlecode.icegem.cacheutils.common.Utils;
import com.googlecode.icegem.cacheutils.monitor.controller.event.NodeEvent;
import com.googlecode.icegem.cacheutils.monitor.controller.event.NodeEventHandler;
import com.googlecode.icegem.cacheutils.monitor.controller.model.Node;
import com.googlecode.icegem.cacheutils.monitor.controller.model.NodesContainer;
import com.googlecode.icegem.cacheutils.monitor.utils.EmailService;
import com.googlecode.icegem.utils.PropertiesHelper;

public class NodesController {

	private NodesContainer nodes = new NodesContainer();
	private AdminService adminService;
	private PropertiesHelper propertiesHelper;
	private PoolFactory poolFactory;
	private BufferedNodeEventHandler bufferedNodeEventHandler;
	private long timeout;

	public NodesController(PropertiesHelper propertiesHelper, String locators,
		long timeout) throws Exception {

		this.propertiesHelper = propertiesHelper;
		this.timeout = timeout;

		adminService = new AdminService(locators, false);

		poolFactory = PoolManager.createFactory();
		bufferedNodeEventHandler = new BufferedNodeEventHandler();
		nodes.addNodeEventHandler(bufferedNodeEventHandler);
	}

	/**
	 * Extracts port from the SystemMember object.
	 *
	 * @param member
	 *            - the specified SystemMember
	 * @return - port if its found, -1 otherwise
	 * @throws AdminException
	 */
	private Set<Integer> extractPortsSet(SystemMember member)
		throws AdminException {
		Set<Integer> portsSet = new HashSet<Integer>();
		SystemMemberCache cache = member.getCache();
		if (cache != null) {
			SystemMemberCacheServer[] cacheServers = cache.getCacheServers();
			if (cacheServers != null) {
				for (SystemMemberCacheServer cacheServer : cacheServers) {
					portsSet.add(cacheServer.getPort());
				}
			}
		}

		return portsSet;
	}

	/**
	 * Looks for the existing pool with name poolFactory. If there is no such
	 * pool, creates new one.
	 *
	 * @param host
	 *            - the concrete server's host
	 * @param port
	 *            - the concrete server's port
	 * @return found or new pool for the specified parameters
	 */
	private Pool findOrCreatePool(String host, int port) {
		String poolName = Utils.toKey(host, port);
		Pool pool = PoolManager.find(poolName);
		if (pool == null) {
			poolFactory.reset();
			poolFactory.addServer(host, port);
			pool = poolFactory.create(poolName);
		}

		return pool;
	}

	private void detectNewNodes() throws AdminException {
		Set<SystemMember> allNodesSet = new HashSet<SystemMember>();

		SystemMember[] systemMemberApplications = adminService.getAdmin()
			.getSystemMemberApplications();

		allNodesSet.addAll(Arrays.asList(systemMemberApplications));

		SystemMember[] cacheVms = adminService.getAdmin().getCacheVms();

		allNodesSet.addAll(Arrays.asList(cacheVms));

		for (SystemMember member : allNodesSet) {
			String host = member.getHost();
			try {
				Set<Integer> portsSet = extractPortsSet(member);
				for (int port : portsSet) {
					Node node = nodes.find(host, port);
					if (node == null) {
						Pool pool = findOrCreatePool(host, port);
						node = new Node(host, port, pool);
						nodes.add(node);
					}
				}
			} catch (OperationCancelledException oce) {
				// do nothing
			}
		}
	}

	private boolean isOperable(Pool pool) {
		boolean operable = false;

		FunctionExecutionThread functionExecutionThread = new FunctionExecutionThread(
			pool);
		Utils.execute(functionExecutionThread, timeout);
		int zero = functionExecutionThread.getZero();

		if (zero == 0) {
			operable = true;
		}

		return operable;
	}

	private void detectDeadNodes() {
		for (Node node : nodes.getAll()) {
			boolean operable = isOperable(node.getPool());

			if (operable) {
				nodes.markAsAlive(node);
			} else {
				nodes.markAsDead(node);
			}
		}
	}

	private void processDeadNodes() {
		for (Node node : nodes.getAllDead()) {
			boolean socketAlive = Utils.isSocketAlive(node.getHost(),
				node.getPort());

			if (!socketAlive) {
				nodes.remove(node);
			}
		}
	}

	private void sendAlertEmail() throws MessagingException {
		List<NodeEvent> eventsList = bufferedNodeEventHandler
			.getAndClearEventslist();

		// send alert email
		if (eventsList.size() > 0) {
			EmailService
				.getInstance()
				.send(
					propertiesHelper
						.getStringProperty("icegem.cacheutils.monitor.email.alert.subject"),
					propertiesHelper.getStringProperty(
						"icegem.cacheutils.monitor.email.alert.content",
						toContentStringHTML(eventsList), Utils.currentDate()));
		}
	}

	private String toContentStringHTML(List<NodeEvent> eventslist) {
		StringBuilder sb = new StringBuilder();

		sb.append("
");
		sb.append("
");
		sb.append("
");
		sb.append("Event date	");
		sb.append("Event type	");
		sb.append("Node	");
		sb.append("
");
		for (NodeEvent event : eventslist) {
			sb.append("
");
			sb.append("").append(Utils.dateToString(event.getCreatedAt()))
				.append("	");
			sb.append("").append(event.getType()).append("	");
			sb.append("").append(event.getNode()).append("	");
			sb.append("
");
		}
		sb.append("
");
		sb.append("
");

		return sb.toString();
	}

	public void update() throws AdminException, MessagingException {
		detectNewNodes();
		detectDeadNodes();
		processDeadNodes();
		sendAlertEmail();
	}

	public boolean isServerAlive(String host, int port) {
		Pool pool = findOrCreatePool(host, port);
		return isOperable(pool);
	}

	public void addNodeEventHandler(NodeEventHandler handler) {
		nodes.addNodeEventHandler(handler);
	}

	public void shutdown() {
		adminService.close();
	}
}


/*-
 * #%L
 * Nazgul Project: nazgul-tools-checkstyle-maven-plugin
 * %%
 * Copyright (C) 2010 - 2018 jGuru Europe AB
 * %%
 * Licensed under the jGuru Europe AB license (the "License"), based
 * on Apache License, Version 2.0; you may not use this file except
 * in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *       http://www.jguru.se/licenses/jguruCorporateSourceLicense-2.0.txt
 *
 * 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.
 * #L%
 */

package se.jguru.nazgul.tools.plugin.checkstyle;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

import com.puppycrawl.tools.checkstyle.api.AuditEvent;

/**
 * Tooling for Checkstyle rules conventions: names, categories.
 *
 * @author Hervé Boutemy
 * @since 2.13
 */
public final class RuleUtil {

    private RuleUtil() {
        // hide utility class constructor
    }

    private static final String CHECKSTYLE_PACKAGE = "com.puppycrawl.tools.checkstyle.checks";

    /**
     * Get the rule name from an audit event.
     *
     * @param event the audit event
     * @return the rule name, which is the class name without package and removed eventual "Check" suffix
     */
    public static String getName(AuditEvent event) {
        return getName(event.getSourceName());
    }

    /**
     * Get the rule name from an audit event source name.
     *
     * @param eventSrcName the audit event source name
     * @return the rule name, which is the class name without package and removed eventual "Check" suffix
     */
    public static String getName(String eventSrcName) {
        if (eventSrcName == null) {
            return null;
        }

        if (eventSrcName.endsWith("Check")) {
            eventSrcName = eventSrcName.substring(0, eventSrcName.length() - 5);
        }

        return eventSrcName.substring(eventSrcName.lastIndexOf('.') + 1);
    }

    /**
     * Get the rule category from an audit event.
     *
     * @param event the audit event
     * @return the rule category, which is the last package name or "misc" or "extension"
     */
    public static String getCategory(AuditEvent event) {
        return getCategory(event.getSourceName());
    }

    /**
     * Get the rule category from an audit event source name.
     *
     * @param eventSrcName the audit event source name
     * @return the rule category, which is the last package name or "misc" or "extension"
     */
    public static String getCategory(String eventSrcName) {
        if (eventSrcName == null) {
            return null;
        }

        int end = eventSrcName.lastIndexOf('.');
        eventSrcName = eventSrcName.substring(0, end);

        if (CHECKSTYLE_PACKAGE.equals(eventSrcName)) {
            return "misc";
        } else if (!eventSrcName.startsWith(CHECKSTYLE_PACKAGE)) {
            return "extension";
        }

        return eventSrcName.substring(eventSrcName.lastIndexOf('.') + 1);
    }

    public static Matcher[] parseMatchers(String[] specs) {
        Matcher[] matchers = new Matcher[specs.length];
        int i = 0;
        for (String spec : specs) {
            spec = spec.trim();
            Matcher matcher;
            if (Character.isUpperCase(spec.charAt(0))) {
                // spec starting with uppercase is a rule name
                matcher = new RuleMatcher(spec);
            } else if ("misc".equals(spec)) {
                // "misc" is a special case
                matcher = new PackageMatcher(CHECKSTYLE_PACKAGE);
            } else if ("extension".equals(spec)) {
                // "extension" is a special case
                matcher = new ExtensionMatcher();
            } else if (!spec.contains(".")) {
                matcher = new PackageMatcher(CHECKSTYLE_PACKAGE + '.' + spec);
            } else {
                // by default, spec is a package name
                matcher = new PackageMatcher(spec);
            }
            matchers[i++] = matcher;
        }
        return matchers;
    }

    /**
     * Audit event source name matcher.
     */
    public interface Matcher {
        /**
         * Does the event source name match?
         *
         * @param eventSrcName the event source name
         * @return boolean
         */
        boolean match(String eventSrcName);
    }

    private static class RuleMatcher
            implements Matcher {
        private final String rule;

        public RuleMatcher(String rule) {
            this.rule = rule;
        }

        public boolean match(String eventSrcName) {
            return rule.equals(getName(eventSrcName));
        }
    }

    private static class PackageMatcher
            implements Matcher {
        private final String packageName;

        public PackageMatcher(String packageName) {
            this.packageName = packageName;
        }

        public boolean match(String eventSrcName) {
            return eventSrcName.startsWith(packageName)
                    && !eventSrcName.substring(packageName.length() + 1).contains(".");
        }
    }

    /**
     * An extension does not start with Checkstyle package.
     */
    private static class ExtensionMatcher
            implements Matcher {
        public boolean match(String eventSrcName) {
            return !eventSrcName.startsWith(CHECKSTYLE_PACKAGE);
        }
    }
}


/*-
 * #%L
 * Nazgul Project: nazgul-tools-visualization-spi-doclet
 * %%
 * Copyright (C) 2010 - 2018 jGuru Europe AB
 * %%
 * Licensed under the jGuru Europe AB license (the "License"), based
 * on Apache License, Version 2.0; you may not use this file except
 * in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *       http://www.jguru.se/licenses/jguruCorporateSourceLicense-2.0.txt
 *
 * 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.
 * #L%
 */

package se.jguru.nazgul.tools.visualization.spi.doclet.javadoc;

import com.sun.javadoc.ClassDoc;
import com.sun.javadoc.PackageDoc;
import com.sun.javadoc.RootDoc;
import com.sun.javadoc.SeeTag;
import com.sun.javadoc.SourcePosition;
import com.sun.javadoc.Tag;

import java.io.Serializable;

/**
 * Abstract RootDoc wrapper which delegates all calls to the original/wrapped RootDoc instance.
 * Intended to be overridden by subclasses.
 *
 * @author Lennart Jörelid, jGuru Europe AB
 * @see RootDoc
 */
public abstract class AbstractRootDocWrapper implements RootDoc, Serializable {

    /**
     * The wrapped, non-null RootDoc instance.
     */
    protected RootDoc wrappedRootDoc;

    /**
     * Constructs an {@link AbstractRootDocWrapper} instance around the supplied {@link RootDoc}.
     *
     * @param wrappedRootDoc A non-null {@link RootDoc} instance to be wrapped by this {@link AbstractRootDocWrapper}.
     */
    public AbstractRootDocWrapper(final RootDoc wrappedRootDoc) {

        // Check sanity
        if (wrappedRootDoc == null) {
            throw new NullPointerException("Cannot handle null 'wrappedRootDoc' argument.");
        }

        // Assign internal state
        this.wrappedRootDoc = wrappedRootDoc;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String[][] options() {
        return wrappedRootDoc.options();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public PackageDoc[] specifiedPackages() {
        return wrappedRootDoc.specifiedPackages();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ClassDoc[] specifiedClasses() {
        return wrappedRootDoc.specifiedClasses();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ClassDoc[] classes() {
        return wrappedRootDoc.classes();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public PackageDoc packageNamed(final String name) {
        return wrappedRootDoc.packageNamed(name);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ClassDoc classNamed(final String qualifiedName) {
        return wrappedRootDoc.classNamed(qualifiedName);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String commentText() {
        return wrappedRootDoc.commentText();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Tag[] tags() {
        return wrappedRootDoc.tags();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Tag[] tags(final String tagname) {
        return wrappedRootDoc.tags(tagname);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public SeeTag[] seeTags() {
        return wrappedRootDoc.seeTags();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Tag[] inlineTags() {
        return wrappedRootDoc.inlineTags();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Tag[] firstSentenceTags() {
        return wrappedRootDoc.firstSentenceTags();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getRawCommentText() {
        return wrappedRootDoc.getRawCommentText();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setRawCommentText(final String rawDocumentation) {
        wrappedRootDoc.setRawCommentText(rawDocumentation);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String name() {
        return wrappedRootDoc.name();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int compareTo(final Object obj) {
        return wrappedRootDoc.compareTo(obj);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isField() {
        return wrappedRootDoc.isField();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isEnumConstant() {
        return wrappedRootDoc.isEnumConstant();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isConstructor() {
        return wrappedRootDoc.isConstructor();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isMethod() {
        return wrappedRootDoc.isMethod();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isAnnotationTypeElement() {
        return wrappedRootDoc.isAnnotationTypeElement();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isInterface() {
        return wrappedRootDoc.isInterface();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isException() {
        return wrappedRootDoc.isException();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isError() {
        return wrappedRootDoc.isError();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isEnum() {
        return wrappedRootDoc.isEnum();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isAnnotationType() {
        return wrappedRootDoc.isAnnotationType();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isOrdinaryClass() {
        return wrappedRootDoc.isOrdinaryClass();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isClass() {
        return wrappedRootDoc.isClass();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isIncluded() {
        return wrappedRootDoc.isIncluded();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public SourcePosition position() {
        return wrappedRootDoc.position();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void printError(final String msg) {
        wrappedRootDoc.printError(msg);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void printError(final SourcePosition pos, final String msg) {
        wrappedRootDoc.printError(pos, msg);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void printWarning(final String msg) {
        wrappedRootDoc.printWarning(msg);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void printWarning(final SourcePosition pos, final String msg) {
        wrappedRootDoc.printWarning(pos, msg);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void printNotice(final String msg) {
        wrappedRootDoc.printNotice(msg);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void printNotice(final SourcePosition pos, final String msg) {
        wrappedRootDoc.printNotice(pos, msg);
    }
}


/*
 * Icegem, Extensions library for VMWare vFabric GemFire
 *
 * Copyright (c) 2010-2011, Grid Dynamics Consulting Services Inc. or third-party
 * contributors as indicated by the @author tags or express copyright attribution
 * statements applied by the authors.
 *
 * This copyrighted material is made available to anyone wishing to use, modify,
 * copy, or redistribute it subject to the terms and conditions of the GNU
 * Lesser General Public License v3, as published by the Free Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * You should have received a copy of the GNU Lesser General Public License v3
 * along with this distribution; if not, write to:
 * Free Software Foundation, Inc.
 * 51 Franklin Street, Fifth Floor
 * Boston, MA  02110-1301  USA
 */
package com.googlecode.icegem.serialization.codegen;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * This counter is a build-in mechanism for detecting circular references.
 * By default it is disabled. It can be enabled by using java property.
 * This property can be set via JVM parameters
 * -Dicegem.serialization.trace.methodframes=true
 * or from the code using the following command:
 * System.setProperty(MethodFrameCounter.SYSTEM_PROPERTY_NAME, "true");
 *
 * Analog of javassist.runtime.Cflow
 *
 * @author igolovach
 * @author Andrey Stepanov
 */
public class MethodFrameCounter extends ThreadLocal<AtomicInteger> {
    public final static String SYSTEM_PROPERTY_NAME = "icegem.serialization.trace.methodframes";
    public static boolean ENABLED = Boolean.getBoolean(SYSTEM_PROPERTY_NAME);

    public final static int MAX_STACK_DEPTH = 256;
    public final static String STACK_OVERFLOW_MSG = "Too deep method frame stack - " + MAX_STACK_DEPTH + ". Perhaps cyclic references in serialized object have been found.";

    private static final ThreadLocal<AtomicInteger> local = new ThreadLocal<AtomicInteger>() {
        protected synchronized AtomicInteger initialValue() {
            return new AtomicInteger(0);
        }
    };

    private static final ThreadLocal<List<String>> classNames = new ThreadLocal<List<String>>() {
        protected synchronized List<String> initialValue() {
            return new ArrayList<String>();
        }
    };

    /**
     * Increment the counter.
     * @param className name of class to enter.
     */
    public static void enterFrame(String className) {
        int counter = local.get().incrementAndGet();
        classNames.get().add(className);
        if (counter == MAX_STACK_DEPTH) {
            throw new RuntimeException(STACK_OVERFLOW_MSG + getClassNames());
        }
    }

    /**
     * Decrement the counter and remove class name from the list.
     * @param className name of class to exit from.
     */
    public static void exitFrame(String className) {
        int counter = local.get().decrementAndGet();
        if (counter < 0) {
            String errorMessage = "Method frame counter is less then 0. Some programming error: count(exitFrame) > count(enterFrame)."
                    + getClassNames();
            clearCounter();
            throw new RuntimeException(errorMessage);
        }
        String frameToExit = classNames.get().remove(classNames.get().size() - 1);
        if (!className.equals(frameToExit)) {
            throw new RuntimeException("Method frame counter try to exit from the class '" + className
                    + "' but must exit from the class '" + frameToExit + "' first." + getClassNames());
        }
    }

    /**
     * Clear the counter and list of class names.
     */
    private static void clearCounter() {
        local.get().set(0);
        classNames.get().clear();
    }

    /**
     * Creates string with all classes that have been entered by method frame counter.
     * @return String
     */
    private static String getClassNames() {
        StringBuilder result = new StringBuilder("\nMethod frame counter enter to the following classes:\n");
        for (String className : classNames.get()) {
            result.append(className).append("\n");
        }
        return result.toString();
    }
}


/*
 * Icegem, Extensions library for VMWare vFabric GemFire
 *
 * Copyright (c) 2010-2011, Grid Dynamics Consulting Services Inc. or third-party
 * contributors as indicated by the @author tags or express copyright attribution
 * statements applied by the authors.
 *
 * This copyrighted material is made available to anyone wishing to use, modify,
 * copy, or redistribute it subject to the terms and conditions of the GNU
 * Lesser General Public License v3, as published by the Free Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * You should have received a copy of the GNU Lesser General Public License v3
 * along with this distribution; if not, write to:
 * Free Software Foundation, Inc.
 * 51 Franklin Street, Fifth Floor
 * Boston, MA  02110-1301  USA
 */
package com.googlecode.icegem.serialization.codegen.impl;

import com.googlecode.icegem.serialization.codegen.CodeGenUtils;
import com.googlecode.icegem.serialization.codegen.XProperty;

/**
 * Generate code that
 * 1) read 'custom class' field value from DataInput
 * 2) set it to bean
 * for method DataSerializer.fromData(...)
 *
 * @author igolovach
 */

class FromDataFieldResolveClassByGemFireProcessor {

//    public String process(XProperty field) {
//        String fieldName = field.getField().getName();
//        String fullClassName = field.getField().getType().getName();
//        String shortClassName = field.getField().getType().getSimpleName();
//
//        return "if (in.readByte() != 0) {\n" +
//                CodeGenUtils.tab("result.set" + CodeGenUtils.firstLetterToUpperCase(fieldName) + "(" +
//                        "(" + fullClassName + ") " +
//                        "new " + CodeGenUtils.DATA_SERIALIZER_PACKAGE + "." + shortClassName + "DataSerializer().fromData(in)" +
//                        ");\n")
//                + "}\n";
//    }

    public String process(XProperty field) {
        String fieldName = field.getName();
        String fullClassName = CodeGenUtils.className(field.getType());

        return "if (in.readByte() != 0) {\n" +
                CodeGenUtils.tab("result.set" + CodeGenUtils.firstLetterToUpperCase(fieldName) + "(" +
                        "(" + fullClassName + ") " +
                        "com.gemstone.gemfire.DataSerializer.readObject(in)" +
                        ");\n")
                + "}\n";
    }
}


/*
 * #%L
 * Nazgul Project: nazgul-tools-codestyle
 * %%
 * Copyright (C) 2010 - 2015 jGuru Europe AB
 * %%
 * Licensed under the jGuru Europe AB license (the "License"), based
 * on Apache License, Version 2.0; you may not use this file except
 * in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *        http://www.jguru.se/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.
 * #L%
 */
package se.jguru.nazgul.tools.codestyle.enforcer.rules;

import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
import org.apache.maven.project.MavenProject;
import se.jguru.nazgul.tools.codestyle.enforcer.rules.source.JavaPackageExtractor;
import se.jguru.nazgul.tools.codestyle.enforcer.rules.source.PackageExtractor;

import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;

/**
 * Enforcer rule to enforce correct packaging for all source files within a project,
 * implying that all source files should be located within or under a package identical
 * to the groupId of the project itself.
 *
 * @author Lennart Jörelid, jGuru Europe AB
 */
public class CorrectPackagingRule extends AbstractNonCacheableEnforcerRule {

    // Constants
    private static final FileFilter DIRECTORY_FILTER = new FileFilter() {
        @Override
        public boolean accept(final File candidate) {
            return candidate.isDirectory();
        }
    };

    /**
     * The default List of PackageExtractors used to identify packages within found source files.
     */
    public static final List<PackageExtractor> DEFAULT_PACKAGE_EXTRACTORS = Arrays.asList(
            (PackageExtractor) new JavaPackageExtractor());

    // Internal state
    private List<PackageExtractor> packageExtractors;

    /**
     * Default constructor, assigning the {@code DEFAULT_PACKAGE_EXTRACTORS} for
     * use as all known PackageExtractor instances.
     */
    public CorrectPackagingRule() {

        // Use the default package extractor List
        packageExtractors = DEFAULT_PACKAGE_EXTRACTORS;
    }

    /**
     * Delegate method, implemented by concrete subclasses.
     *
     * @param project The active MavenProject.
     * @param helper  The EnforcerRuleHelper instance, from which the MavenProject has been retrieved.
     * @throws RuleFailureException If the enforcer rule was not satisfied.
     */
    @Override
    @SuppressWarnings("unchecked")
    protected void performValidation(final MavenProject project, final EnforcerRuleHelper helper)
            throws RuleFailureException {

        // Find all java source files, and map their packages to their names.
        final List<String> compileSourceRoots = (List<String>) project.getCompileSourceRoots();
        if (compileSourceRoots.size() == 0) {
            return;
        }

        final SortedMap<String, SortedSet<String>> packageName2SourceFileNameMap
                = new TreeMap<String, SortedSet<String>>();

        for (String current : compileSourceRoots) {
            addPackages(new File(current), packageName2SourceFileNameMap);
        }

        // Retrieve the groupId of this project
        final String groupId = project.getGroupId();
        if (groupId == null || groupId.equals("")) {

            // Don't accept empty groupIds
            throw new RuleFailureException("Maven groupId cannot be null or empty.", project.getArtifact());

        } else {

            // Correct packaging everywhere?
            final SortedSet<String> incorrectPackages = new TreeSet<String>();
            for (Map.Entry<String, SortedSet<String>> currentPackage : packageName2SourceFileNameMap.entrySet()) {

                final String candidate = currentPackage.getKey();
                if (!candidate.startsWith(groupId)) {
                    incorrectPackages.add(candidate);
                }
            }

            if (incorrectPackages.size() > 0) {

                final SortedMap<String, SortedSet<String>> result = new TreeMap<String, SortedSet<String>>();
                for (String current : incorrectPackages) {
                    result.put(current, packageName2SourceFileNameMap.get(current));
                }

                throw new RuleFailureException("Incorrect packaging detected; required [" + groupId
                        + "] but found package to file names: " + result, project.getArtifact());
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected String getShortRuleDescription() {
        return "Topmost source package must be identical to project groupId.";
    }

    /**
     * Splices the supplied packageExtractorImplementations argument, which is assumed to be a comma-separated
     * string holding fully qualified class names of the PackageExtractor implementations which should be used
     * by this CorrectPackagingRule.
     *
     * @param packageExtractorImplementations a comma-separated string holding fully qualified class names of the
     *                                        PackageExtractor implementations. Each such class must have a default
     *                                        (i.e. no-argument) constructor.
     * @throws IllegalArgumentException if the supplied packageExtractorImplementations argument could not yield an
     *                                  instantiated PackageExtractor instance.
     */
    public final void setPackageExtractors(final String packageExtractorImplementations)
            throws IllegalArgumentException {

        // Check sanity
        if(packageExtractorImplementations == null) {
            throw new NullPointerException("Cannot handle empty packageExtractorImplementations argument.");
        }

        // Instantiate the PackageExtractor instances.
        List<PackageExtractor> extractors = new ArrayList<PackageExtractor>();
        for (String current : splice(packageExtractorImplementations)) {
            try {

                // Load the current PackageExtractor implementation class
                final Class<?> aClass = getClass().getClassLoader().loadClass(current);

                // The PackageExtractor implementation must have a default constructor.
                // Fire, and handle any exceptions.
                extractors.add((PackageExtractor) aClass.newInstance());
            } catch (Exception e) {
                throw new IllegalArgumentException("Could not instantiate PackageExtractor from class ["
                        + current + "]. Validate that implementation has a default constructor, and implements the"
                        + PackageExtractor.class.getSimpleName() + " interface.");
            }
        }

        // Assign if non-null.
        if (extractors.size() > 0) {
            this.packageExtractors = extractors;
        }
    }

    //
    // Private helpers
    //

    /**
     * Adds all source file found by recursive search under sourceRoot to the
     * toPopulate List, using a width-first approach.
     *
     * @param fileOrDirectory      The file or directory to search for packages and [if a directory] recursively
     *                             search for further source files.
     * @param package2FileNamesMap A Map relating package names extracted by the PackageExtractors.
     */
    private void addPackages(final File fileOrDirectory,
                             final SortedMap<String, SortedSet<String>> package2FileNamesMap) {

        for (PackageExtractor current : packageExtractors) {

            final FileFilter sourceFileDefinitionFilter = current.getSourceFileFilter();

            if (fileOrDirectory.isFile() && sourceFileDefinitionFilter.accept(fileOrDirectory)) {

                // Single source file to add.
                final String thePackage = current.getPackage(fileOrDirectory);

                SortedSet<String> sourceFileNames = package2FileNamesMap.get(thePackage);
                if (sourceFileNames == null) {
                    sourceFileNames = new TreeSet<String>();
                    package2FileNamesMap.put(thePackage, sourceFileNames);
                }

                // Done.
                sourceFileNames.add(fileOrDirectory.getName());

            } else if (fileOrDirectory.isDirectory()) {

                // Add the immediate source files
                for (File currentChild : fileOrDirectory.listFiles(sourceFileDefinitionFilter)) {
                    addPackages(currentChild, package2FileNamesMap);
                }

                // Recurse into subdirectories
                for (File currentSubdirectory : fileOrDirectory.listFiles(DIRECTORY_FILTER)) {
                    addPackages(currentSubdirectory, package2FileNamesMap);
                }
            }
        }
    }
}