/*
	(c) Copyright 2005, 2006, Hewlett-Packard Development Company, LP
  	[See end of file]
 	$Id: BidiMapImpl.java,v 1.1 2006/09/22 15:14:25 rebach Exp $
*/
package org.wymiwyg.commons.util.collections;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author reto
 *
 */
public class BidiMapImpl<K,V> implements BidiMap<K, V> {

	private final Map<K,V> forward;
	private final Map<V,K> backward;

	/**
	 *
	 */
	public BidiMapImpl() {
		forward = new HashMap<K,V>();
		backward = new HashMap<V,K>();
	}

	private BidiMapImpl(final Map<K,V> forward, final Map<V,K> backward) {
		this.forward = forward;
		this.backward = backward;
	}

	/* (non-Javadoc)
	 * @see org.wymiwyg.rdf.molecules.store.BidiMap#getKey(U)
	 */
	public K getKey(V value) {
		return backward.get(value);
	}

	/* (non-Javadoc)
	 * @see java.util.Map#size()
	 */
	public int size() {
		return forward.size();
	}

	/* (non-Javadoc)
	 * @see java.util.Map#isEmpty()
	 */
	public boolean isEmpty() {
		return forward.isEmpty();
	}

	/* (non-Javadoc)
	 * @see java.util.Map#containsKey(java.lang.Object)
	 */
	public boolean containsKey(Object key) {
		return forward.containsKey(key);
	}

	/* (non-Javadoc)
	 * @see java.util.Map#containsValue(java.lang.Object)
	 */
	public boolean containsValue(Object value) {
		return backward.containsKey(value);
	}

	/* (non-Javadoc)
	 * @see java.util.Map#get(java.lang.Object)
	 */
	public V get(Object key) {
		return forward.get(key);
	}

	/* (non-Javadoc)
	 * @see java.util.Map#put(K, V)
	 */
	public V put(K key, V value) {
		//remove possible existing with same value

		if (backward.containsKey(value)) {
			K oldKey = backward.get(value);
			forward.remove(oldKey);
		}
		if (forward.containsKey(key)) {
			V oldValue = forward.get(key);
			backward.remove(oldValue);
		}
		backward.put(value, key);
		return forward.put(key, value);
	}

	/* (non-Javadoc)
	 * @see java.util.Map#remove(java.lang.Object)
	 */
	public V remove(Object key) {
		V value = forward.remove(key);
		backward.remove(value);
		return value;
	}

	/* (non-Javadoc)
	 * @see java.util.Map#putAll(java.util.Map)
	 */
	public void putAll(Map<? extends K, ? extends V> m) {
		for (Entry<? extends K, ? extends V> entry : m.entrySet()) {
			put(entry.getKey(), entry.getValue());
		}

	}

	/* (non-Javadoc)
	 * @see java.util.Map#clear()
	 */
	public void clear() {
		forward.clear();
		backward.clear();

	}

	/* (non-Javadoc)
	 * @see java.util.Map#keySet()
	 */
	public Set<K> keySet() {
		return forward.keySet();
	}

	/* (non-Javadoc)
	 * @see java.util.Map#values()
	 */
	public Collection<V> values() {
		return backward.keySet();
	}

	/* (non-Javadoc)
	 * @see java.util.Map#entrySet()
	 */
	public Set<Entry<K,V>> entrySet() {
		return forward.entrySet();
	}

	public BidiMap<V, K> inverse() {
		return new BidiMapImpl(backward, forward);
	}

}
/*
(c) Copyright 2005, 2006 Hewlett-Packard Development Company, LP
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.

3. The name of the author may not be used to endorse or promote products
   derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*/


// Copyright (c) 2014 Morgan Stanley & Co. Incorporated, All Rights Reserved

package ca.jeb.protobuf.internal;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.sql.Date;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;

import ca.jeb.common.infra.JReflectionUtils;
import ca.jeb.common.infra.JStringUtils;
import ca.jeb.protobuf.ProtobufAttribute;
import ca.jeb.protobuf.ProtobufEntity;

import com.google.protobuf.GeneratedMessage;

/**
 * Utility class to help out the ProtobufSerializer.
 *
 * @author Erick Bourgeois
 */
public final class ProtobufSerializerUtils
{
  private static final Map<String, Map<Field, ProtobufAttribute>> CLASS_TO_FIELD_MAP_CACHE         = Collections
                                                                                .synchronizedMap(new WeakHashMap<String, Map<Field, ProtobufAttribute>>());

  // Internal cache to hold onto Class -> fieldName -> setter
  private static final Map<String, Map<String, String>>           CLASS_TO_FIELD_SETTERS_MAP_CACHE = Collections
                                                                                .synchronizedMap(new WeakHashMap<String, Map<String, String>>());

  // Internal cache to hold onto Class -> fieldName -> getter
  private static final Map<String, Map<String, String>>           CLASS_TO_FIELD_GETTERS_MAP_CACHE = Collections
                                                                                .synchronizedMap(new WeakHashMap<String, Map<String, String>>());

  /**
   * Retrieve the ProtobufClass based on the POJO value. The returned value may get converted,
   * as the Protobuf builders/setters use primitives. For example, if user has declared Integer,
   * this get's converted to int.
   *
   * @param value - POJO object
   * @param protobufClass - the Protobuf class
   * @return Class<? extends Object> - actual Protobuf class to use in setter
   */
  public static final Class<? extends Object> getProtobufClass(Object value, Class<? extends Object> protobufClass)
  {
    if (value instanceof Integer)
    {
      return Integer.TYPE;
    }
    if (value instanceof Boolean)
    {
      return Boolean.TYPE;
    }
    if (value instanceof Double)
    {
      return Double.TYPE;
    }
    if (value instanceof Long || value instanceof Date)
    {
      return Long.TYPE;
    }
    if (value instanceof List)
    {
      return Iterable.class;
    }
    return protobufClass;
  }

  /**
   * Return a ProtobufEntity annotation from any object sent, null if there is none.
   *
   * @param clazz - any Class
   * @return ProtobufEntity annotation
   * @see ca.jeb.protobuf.ProtobufEntity
   */
  public static final ProtobufEntity getProtobufEntity(Class<?> clazz)
  {
    final ProtobufEntity protoBufEntity = clazz.getAnnotation(ProtobufEntity.class);

    if (protoBufEntity != null)
    {
      return protoBufEntity;
    }

    return null;
  }

  /**
   * Returns true if there is a ProtobufEntity annotation on this object.
   *
   * @param object - a POJO object
   * @return boolean - true, if there is a ProtobufEntity annotation, else, false
   * @see ProtobufEntity
   */
  public static final boolean isProtbufEntity(Object object)
  {
    return isProtbufEntity(object.getClass());
  }

  /**
   * Returns true if there is a ProtobufEntity annotation on this class.
   *
   * @param clazz - any Class
   * @return boolean - true, if there is a ProtobufEntity annotation, else, false
   * @see ProtobufEntity
   */
  public static final boolean isProtbufEntity(Class<?> clazz)
  {
    final ProtobufEntity protoBufEntity = getProtobufEntity(clazz);

    if (protoBufEntity != null)
    {
      return true;
    }
    return false;
  }

  /**
   * Return the Protobuf Class based on the pojo class, i.e. grab the value from the ProtobufEntity annotation.
   *
   * @param clazz - any Class
   * @return Class<? extends GeneratedMessage>
   */
  public static final Class<? extends GeneratedMessage> getProtobufClassFromPojoAnno(Class<?> clazz)
  {
    final ProtobufEntity annotation = getProtobufEntity(clazz);
    final Class<? extends GeneratedMessage> gpbClazz = (Class<? extends GeneratedMessage>)annotation.value();
    if (gpbClazz == null)
    {
      return null;
    }
    return gpbClazz;
  }

  /**
   * Returns a full mapping of all Protobuf fields from the POJO class.
   * Essentially, the only fields that will be returned if they have
   * the ProtobufAttribute annotation.
   *
   * @param fromClazz - Class<? extends Object>
   * @return Map<Field, ProtobufAttribute>
   */
  public static final Map<Field, ProtobufAttribute> getAllProtbufFields(Class<? extends Object> fromClazz)
  {
    Map<Field, ProtobufAttribute> protoBufFields = CLASS_TO_FIELD_MAP_CACHE.get(fromClazz.getCanonicalName());
    if (protoBufFields != null)
    {
      return protoBufFields;
    }
    else
    {
      protoBufFields = new HashMap<>();
    }

    final List<Field> fields = JReflectionUtils.getAllFields(new ArrayList<Field>(), fromClazz);

    for (Field field : fields)
    {
      final Annotation annotation = field.getAnnotation(ProtobufAttribute.class);
      if (annotation == null)
      {
        continue;
      }
      final ProtobufAttribute gpbAnnotation = (ProtobufAttribute)annotation;
      protoBufFields.put(field, gpbAnnotation);
    }

    // Caching to increase speed
    CLASS_TO_FIELD_MAP_CACHE.put(fromClazz.getCanonicalName(), protoBufFields);

    return protoBufFields;
  }

  /*
   * Setter and Getter Utilities
   */

  /**
   * Return the setter for the Protobuf builder.

   * 1. Defaults to just "set" + upper case the first character of the fieldName.
   * 2. If it's a collection, use the "addAll" type method Protobuf has
   * 3. Otherwise, use the override value from the user's ProtobufAttribute annotation

   *
   * @param protobufAttribute - {@link ProtobufAttribute}
   * @param field - String
   * @param fieldValue - POJO's filed Object
   * @return String - the setter to be used on Protobuf builder
   */
  public static final String getProtobufSetter(ProtobufAttribute protobufAttribute, Field field, Object fieldValue)
  {
    final String fieldName = field.getName();
    final String upperClassName = field.getDeclaringClass().getCanonicalName();
    // Look at the cache first
    Map<String, String> map = CLASS_TO_FIELD_SETTERS_MAP_CACHE.get(upperClassName);
    if (map != null)
    {
      if (!map.isEmpty() && map.containsKey(fieldName))
      {
        return map.get(fieldName);
      }
    }
    else
    {
      map = new ConcurrentHashMap<>();
    }

    String setter = "set" + JStringUtils.upperCaseFirst(fieldName);

    if (fieldValue instanceof Collection)
    {
      setter = "addAll" + JStringUtils.upperCaseFirst(fieldName);
    }

    // Finally override setter with a value that is configured in ProtobufAttribute annotation
    final String configedSetter = protobufAttribute.protobufSetter();
    if (!configedSetter.equals(JStringUtils.EMPTY))
    {
      setter = configedSetter;
    }

    map.put(fieldName, setter);
    CLASS_TO_FIELD_SETTERS_MAP_CACHE.put(upperClassName, map);

    return setter;
  }

  /**
   * Retrieve the getter against the Protobuf class; default is to is "get" plus upper case first character of the field name.
   *
   * @param protobufAttribute - {@link ProtobufAttribute}
   * @param field - {@link Field}
   * @return String
   */
  public static final String getProtobufGetter(ProtobufAttribute protobufAttribute, Field field)
  {
    final String fieldName = field.getName();
    final String upperClassName = field.getDeclaringClass().getCanonicalName();
    // Look at the cache first
    Map<String, String> map = CLASS_TO_FIELD_GETTERS_MAP_CACHE.get(upperClassName);
    if (map != null)
    {
      if (!map.isEmpty() && map.containsKey(fieldName))
      {
        return map.get(fieldName);
      }
    }
    else
    {
      map = new ConcurrentHashMap<>();
    }

    final String upperCaseFirstFieldName = JStringUtils.upperCaseFirst(field.getName());
    String getter = "get" + upperCaseFirstFieldName;

    if (Collection.class.isAssignableFrom(field.getType()))
    {
      getter += "List";
    }
    if (!protobufAttribute.protobufGetter().isEmpty())
    {
      return protobufAttribute.protobufGetter();
    }

    map.put(fieldName, getter);
    CLASS_TO_FIELD_GETTERS_MAP_CACHE.put(upperClassName, map);

    return getter;
  }

  /**
   * Retrieve the setter on the POJO class; default is to is "set" plus upper case first character of the field name.
   *
   * @param protobufAttribute - {@link ProtobufAttribute}
   * @param field - {@link Field}
   * @return String - the name of the POJO setter
   */
  public static final String getPojoSetter(ProtobufAttribute protobufAttribute, Field field)
  {
    final String fieldName = field.getName();
    final String upperClassName = field.getDeclaringClass().getCanonicalName();
    // Look at the cache first
    Map<String, String> map = CLASS_TO_FIELD_SETTERS_MAP_CACHE.get(upperClassName);
    if (map != null)
    {
      if (!map.isEmpty() && map.containsKey(fieldName))
      {
        return map.get(fieldName);
      }
    }
    else
    {
      map = new ConcurrentHashMap<>();
    }

    final String upperCaseFirstFieldName = JStringUtils.upperCaseFirst(field.getName());
    String setter = "set" + upperCaseFirstFieldName;

    if (!protobufAttribute.pojoSetter().isEmpty())
    {
      return protobufAttribute.pojoSetter();
    }

    map.put(fieldName, setter);
    CLASS_TO_FIELD_SETTERS_MAP_CACHE.put(upperClassName, map);

    return setter;
  }
}


/*
 * #%L
 * This file is part of a universal JAAS library, providing common functionality
 * for a username / password style JAAS module.
 * %%
 * Copyright (C) 2014 - 2016 Michael Beiter <michael@beiter.org>
 * %%
 * All rights reserved.
 * .
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the copyright holder nor the names of the
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 * .
 * .
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
 * #L%
 */
package org.beiter.michael.authn.jaas.loginmodules.password.common;

import org.apache.commons.lang3.Validate;
import org.beiter.michael.authn.jaas.common.CommonProperties;
import org.beiter.michael.authn.jaas.common.FactoryException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * A factory to create instances of objects that implement the {@link PasswordValidator} interface.
 */
public final class PasswordValidatorFactory {

    /**
     * The logger object for this class
     */
    private static final Logger LOG = LoggerFactory.getLogger(PasswordValidatorFactory.class);

    /**
     * The singleton instance of the password validator
     */
    @SuppressWarnings("PMD.LongVariable")
    private static volatile PasswordValidator passwordValidatorInstance;

    /**
     * A private constructor to prevent instantiation of this class
     */
    private PasswordValidatorFactory() {
    }

    /**
     * Return a new, fully initialized instance of a {@link PasswordValidator} class to use for JAAS authentication.
     *

     * Classes implementing the {@link PasswordValidator} interface must be thread safe.
     *
     * @param className  The name of a class that implements the PasswordValidator interface
     * @param properties The properties to initialize the instance with
     * @return An instance of a class implementing the {@code PasswordValidator} interface
     * @throws FactoryException         When the class cannot be instantiated
     * @throws NullPointerException     When the {@code className} or {@code properties} are {@code null}
     * @throws IllegalArgumentException When {@code className} is empty
     */
    public static PasswordValidator getInstance(final String className, final CommonProperties properties)
            throws FactoryException {

        Validate.notBlank(className, "The validated character sequence 'className' is null or empty");
        Validate.notNull(properties, "The validated object 'properties' is null");

        final Class<? extends PasswordValidator> validatorClazz;
        try {
            validatorClazz = Class.forName(className).asSubclass(PasswordValidator.class);
        } catch (ClassNotFoundException e) {
            // Fortify will report a violation here because of disclosure of potentially confidential information.
            // However, the class name is not confidential, which makes this a non-issue / false positive.
            final String error = "Class not found: " + className;
            LOG.warn(error);
            throw new FactoryException(error, e);
        } catch (ClassCastException e) {
            final String error = "The provided registry factory class name ('" + className
                    + "') is not a subclass of '" + PasswordValidator.class.getCanonicalName() + "'";
            LOG.warn(error);
            throw new FactoryException(error, e);
        }

        final PasswordValidator pwValidator;
        try {
            final Constructor<? extends PasswordValidator> constructor
                    = validatorClazz.getDeclaredConstructor();
            if (!constructor.isAccessible()) {
                final String error = "Constructor of class '" + validatorClazz.getCanonicalName()
                        + "' is not accessible, changing the accessible flag to instantiate the class";
                LOG.info(error);
                constructor.setAccessible(true);
            }
            pwValidator = constructor.newInstance();
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException
                | NoSuchMethodException | IllegalArgumentException e) {
            final String error = "Cannot instantiate class '" + validatorClazz.getCanonicalName() + "'";
            LOG.warn(error, e);
            throw new FactoryException(error, e);
        }

        pwValidator.init(properties);

        return pwValidator;
    }

    /**
     * Return a singleton, fully initialized instance of a {@link PasswordValidator} class to use for
     * JAAS authentication.
     *

     * Retrieving a singleton by this method will cause the factory to keep state, and store a reference to the
     * singleton for later use. You may reset the factory state using the {@code reset()} method to retrieve a new
     * / different singleton the next time this method is called..
     *

     * Note that any properties of the singleton (e.g. configuration) cannot necessarily be changed easily. You may call
     * the singleton's {@code init()} method, but depending on the implementation provided by the respective class, this
     * may or may not have the expected effect.
     *

     * If you need tight control over the singleton, including its lifecycle and configuration, or you require more than
     * one singleton that are different in their internal state (e.g. with different configurations), then you should
     * create such objects with the {@code getInstance()} method and maintain their state as "singletons" in your
     * application's business logic.
     *

     * Classes implementing the {@link PasswordValidator} interface must be thread safe.
     *
     * @param className  The name of a class that implements the PasswordValidator interface
     * @param properties The properties to initialize the instance with
     * @return An instance of a class implementing the {@code PasswordValidator} interface
     * @throws FactoryException         When the class cannot be instantiated
     * @throws NullPointerException     When the {@code className} or {@code properties} are {@code null}
     * @throws IllegalArgumentException When {@code className} is empty
     */
    @SuppressWarnings("PMD.NonThreadSafeSingleton")
    public static PasswordValidator getSingleton(final String className, final CommonProperties properties)
            throws FactoryException {

        Validate.notBlank(className, "The validated character sequence 'className' is null or empty");
        Validate.notNull(properties, "The validated object 'properties' is null");

        if (passwordValidatorInstance == null) {
            synchronized (PasswordValidatorFactory.class) {
                if (passwordValidatorInstance == null) {

                    passwordValidatorInstance = getInstance(className, properties);
                }
            }
        }

        return passwordValidatorInstance;
    }

    /**
     * Resets the internal state of the factory, which causes the
     * {@link PasswordAuthenticatorFactory#getSingleton(String, CommonProperties)} method to return a new
     * {@link PasswordAuthenticator} instance the next time it is called.
     */
    // CHECKSTYLE:OFF
    // this is flagged in checkstyle with a missing whitespace before '}', which is a bug in checkstyle
    @SuppressWarnings({"PMD.NonThreadSafeSingleton", "PMD.NullAssignment"})
    // CHECKSTYLE:ON
    public static void reset() {

        // Unset the instance singleton that has been created earlier
        // The double-check idiom is safe and acceptable here (Bloch, 2nd ed. p 284)
        // null-assignments for de-referencing objects are okay
        if (passwordValidatorInstance != null) {
            synchronized (PasswordValidatorFactory.class) {
                if (passwordValidatorInstance != null) {
                    passwordValidatorInstance = null;
                }
            }
        }
    }
}


/*
 * @(#)ScreenApplet.java	1.13 98/08/28
 * Copyright © 2012 jbundle.org. All rights reserved.
 */
package org.jbundle.jbackup.destination;

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.util.Properties;

import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

import org.jbundle.jbackup.JBackupConstants;
import org.jbundle.util.apprunner.PropertyOwner;

/**
 * Main property view screen.
 * From this screen the user selects the model, view, and control.
 */
public class HttpDestinationPropertyView extends BaseDestinationPropertyView
	implements JBackupConstants
{
	private static final long serialVersionUID = 1L;

	protected JTextField m_tfRootPathname = null;

	/*
	 * Constructor.
	 */
	public HttpDestinationPropertyView()
	{
		super();
	}
	/*
	 * Constructor.
	 */
	public HttpDestinationPropertyView(PropertyOwner propOwner,Properties properties)
	{
		this();
		this.init(propOwner, properties);
	}
	/*
	 * Initialize.
	 */
	public void init(PropertyOwner propOwner, Properties properties)
	{
		super.init(propOwner, properties);
	}
	/*
	 * Add your property controls to this panel.
	 * Remember to set your own layout manager.
	 * Also, remember to create a new JPanel, and pass it to the super class
	 * so controls of the superclass can be included.
	 * You have a 3 x 3 grid, so add three columns for each control
	 * @param panel This is the panel to add your controls to.
	 */
	public void addControlsToView(JPanel panel)
	{
		panel.setLayout(new BorderLayout());
		JPanel panelMain = this.makeNewPanel(panel, BorderLayout.CENTER);

		panelMain.setLayout(new GridLayout(2, 2));

		panelMain.add(new JLabel("Root URL: ", JLabel.RIGHT));
		panelMain.add(m_tfRootPathname = new JTextField());

		JPanel panelSub = this.makeNewPanel(panel, BorderLayout.SOUTH);
		super.addControlsToView(panelSub);
	}
	/*
	 * Set the properties to the current control values.
	 */
	public void controlsToProperties()
	{
		super.controlsToProperties();
		String strPathname = m_tfRootPathname.getText();
		m_properties.setProperty(BASE_URL_PARAM, strPathname);
	}
	/*
	 * Set the properties to the current control values.
	 */
	public void propertiesToControls()
	{
		super.propertiesToControls();
		String strPathname = m_properties.getProperty(BASE_URL_PARAM);
		m_tfRootPathname.setText(strPathname);
	}
	/*
	 * Get the description of this option panel.
	 */
	public String getDescription()
	{
		return "Base source properties";
	}
}


/**
 * Copyright 2013-2014 Guoqiang Chen, Shanghai, China. All rights reserved.
 *
 * Email: subchen@gmail.com
 * URL: http://subchen.github.io/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package jetbrick.text.pinyin;

import java.io.*;
import java.util.HashMap;
import java.util.Map;
import jetbrick.io.IoUtils;
import jetbrick.lang.StringUtils;

/**
 * 得到汉字的完整拼音 (支持GBK)
 *
 * @author Guoqiang Chen
 */
public class ChinesePinyin {
    private static ChinesePinyin instance = new ChinesePinyin();
    private Map<String, String[]> pinyinTable = new HashMap<String, String[]>(21000);

    public static ChinesePinyin getInstance() {
        return instance;
    }

    private ChinesePinyin() {
        InputStream is = getClass().getResourceAsStream("ChinesePinyin.dat");
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(is, "ISO-8859-1"));
            String line = null;
            while (true) {
                line = reader.readLine();
                if (line == null) break;

                String hex = StringUtils.substringBefore(line, "=");
                String pinyin = StringUtils.substringAfter(line, "=");
                if (StringUtils.isNotBlank(pinyin)) {
                    pinyinTable.put(hex, pinyin.split(","));
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            IoUtils.closeQuietly(is);
        }
    }

    /**
     * 得到指定的中文字符对应的拼音, 返回值带声调.
     *
     * @return null - 不可识别的字符
     */
    public String[] getPinyinFromChar(char c) {
        String s = Integer.toHexString(c).toUpperCase();
        return pinyinTable.get(s);
    }

    /**
     * 返回中文，删除不可识别的字符.
     */
    public String getChinese(String str) {
        if (str == null) return null;

        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < str.length(); i++) {
            char ch = str.charAt(i);
            if (getPinyinFromChar(ch) != null) {
                sb.append(ch);
            }
        }
        return sb.toString();
    }

    /**
     * 得到字符串对应的拼音(默认小写, 不带声调), 不可识别的字符原样返回.
     */
    public String getFullPinyin(String str) {
        if (str == null) return null;

        StringBuffer sb = new StringBuffer();
        String[] item = null;
        for (int i = 0; i < str.length(); i++) {
            char ch = str.charAt(i);
            item = getPinyinFromChar(ch);
            if (item == null) {
                sb.append(ch);
            } else {
                sb.append(item[0].substring(0, item[0].length() - 1));
            }
        }
        return sb.toString();
    }

    /**
     * 得到字符串对应的拼音首字母(默认小写), 不可识别的字符原样返回.
     */
    public String getFirstPinyin(String str) {
        if (str == null) return null;

        StringBuffer sb = new StringBuffer();
        String[] item = null;
        for (int i = 0; i < str.length(); i++) {
            char ch = str.charAt(i);
            item = getPinyinFromChar(ch);
            if (item == null) {
                sb.append(ch);
            } else {
                sb.append(item[0].substring(0, 1));
            }
        }
        return sb.toString();
    }
}


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

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringWriter;
import java.net.URL;
import java.text.DateFormat;
import java.text.SimpleDateFormat;

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

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

/**
 * JSON UTILS
 *
 * @author RA
 * @since JDK1.6
 * @since JACKSON 2.2.0
 */
public class JsonUtil {

	// ~ Instance fields ==================================================

	/**
	 *
	 */
	private static final Logger log = LoggerFactory.getLogger(JsonUtil.class);
	/**
	 * ObjectMapper
	 */
	private static final ThreadLocal<ObjectMapper> threadMapper = new ThreadLocal<ObjectMapper>();
	/**
	 * JsonFactory
	 */
	private static final ThreadLocal<JsonFactory> threadJsonFactory = new ThreadLocal<JsonFactory>();

	// ~ Constructors ==================================================

	/**
	 */
	private JsonUtil() {

	}

	// ~ Methods ==================================================

	/**
	 * return a ObjectMapper if exist,else new ObjectMapper
	 *
	 * @return ObjectMapper
	 */
	public static ObjectMapper getMapper() {

		ObjectMapper mapper = threadMapper.get();
		if (mapper == null) {
			mapper = initMapper();
			threadMapper.set(mapper);

		}
		return mapper;
	}

	/**
	 * Initialize mapper
	 *
	 * @return initialized {@link ObjectMapper}
	 */
	private static ObjectMapper initMapper() {

		ObjectMapper mapper = new ObjectMapper();
		// to enable standard indentation ("pretty-printing"):
		mapper.enable(SerializationFeature.INDENT_OUTPUT);
		// to allow serialization of "empty" POJOs (no properties to serialize)
		// (without this setting, an exception is thrown in those cases)
		mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
		// set writer flush after writer value
		mapper.enable(SerializationFeature.FLUSH_AFTER_WRITE_VALUE);
		// ObjectMapper will call close() and root values that implement
		// java.io.Closeable;
		// including cases where exception is thrown and serialization does not
		// completely succeed.
		mapper.enable(SerializationFeature.CLOSE_CLOSEABLE);
		// to write java.util.Date, Calendar as number (timestamp):
		mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
		// disable default date to timestamp
		mapper.disable(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS);

		// DeserializationFeature for changing how JSON is read as POJOs:

		// to prevent exception when encountering unknown property:
		mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
		// disable default date to timestamp
		mapper.disable(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS);
		// to allow coercion of JSON empty String ("") to null Object value:
		mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
		DateFormat df = new SimpleDateFormat("yyyyMMddHHmmssSSS");
		// Set Default date fromat
		mapper.setDateFormat(df);

		return mapper;

	}

	/**
	 * return a JsonFactory if exist,else new JsonFactory
	 *
	 * @return JsonFactory
	 */
	public static JsonFactory getJsonFactory() {

		JsonFactory jsonFactory = threadJsonFactory.get();
		if (jsonFactory == null) {
			jsonFactory = new JsonFactory();
			// JsonParser.Feature for configuring parsing settings:
			// to allow C/C++ style comments in JSON (non-standard, disabled by
			// default)
			jsonFactory.enable(JsonParser.Feature.ALLOW_COMMENTS);
			// to allow (non-standard) unquoted field names in JSON:
			jsonFactory.disable(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES);
			// to allow use of apostrophes (single quotes), non standard
			jsonFactory.disable(JsonParser.Feature.ALLOW_SINGLE_QUOTES);

			// JsonGenerator.Feature for configuring low-level JSON generation:

			// no escaping of non-ASCII characters:
			jsonFactory.disable(JsonGenerator.Feature.ESCAPE_NON_ASCII);
			threadJsonFactory.set(jsonFactory);

		}
		return jsonFactory;
	}

	/**
	 * Json string to java bean

	 *

	 * List,Array,Map
	 *

	 *

	 * clazz= new TypeReference<List<MyBean>>(){};
	 *
	 * e.g:
	 * toBean(jsonStr,new TypeReference<List<MyBean>>(){})
	 *
	 * toBean(jsonStr, MyBean[])
	 *
	 * toBean(jsonStr, new TypeReference<Map<String, Map<String, MyBean>>(){})
	 *

	 *
	 * @param jsonStr json String
	 * @param valueTypeRef value type ref
	 * @param <T> t
	 * @return bean
	 */
	public static <T> T toBean(String jsonStr, TypeReference<T> valueTypeRef) {
		if (valueTypeRef == null || jsonStr == null)
			return null;
		return toBean(new MyJsonParser(jsonStr), valueTypeRef);

	}

	/**
	 * Json string to java bean

	 *

	 * List,Array,Map
	 *

	 *

	 * clazz= new TypeReference<List<MyBean>>(){};
	 *
	 * e.g:
	 * toBean(jsonBytes,new TypeReference<List<MyBean>>(){})
	 *
	 * toBean(jsonBytes, MyBean[])
	 *
	 * toBean(jsonBytes, new TypeReference<Map<String, Map<String, MyBean>>(){})
	 *

	 *
	 * @param jsonBytes json bytes
	 * @param valueTypeRef value type ref
	 * @param <T> t
	 * @return bean
	 */
	public static <T> T toBean(byte[] jsonBytes, TypeReference<T> valueTypeRef) {
		if (valueTypeRef == null || jsonBytes == null)
			return null;
		return toBean(new MyJsonParser(jsonBytes), valueTypeRef);

	}

	/**
	 * Json string to java bean

	 *

	 * List,Array,Map
	 *

	 *

	 * clazz= new TypeReference<List<MyBean>>(){};
	 *
	 * e.g:
	 * toBean(jsonReader,new TypeReference<List<MyBean>>(){})
	 *
	 * toBean(jsonReader, MyBean[])
	 *
	 * toBean(jsonReader, new TypeReference<Map<String, Map<String, MyBean>>(){})
	 *

	 *
	 * @param jsonReader json reader
	 * @param valueTypeRef value type ref
	 * @param <T> t
	 * @return bean
	 */
	public static <T> T toBean(Reader jsonReader, TypeReference<T> valueTypeRef) {
		if (valueTypeRef == null || jsonReader == null)
			return null;
		return toBean(new MyJsonParser(jsonReader), valueTypeRef);

	}

	/**
	 * Json string to java bean

	 *

	 * List,Array,Map
	 *

	 *

	 * clazz= new TypeReference<List<MyBean>>(){};
	 *
	 * e.g:
	 * toBean(jsonURL,new TypeReference<List<MyBean>>(){})
	 *
	 * toBean(jsonURL, MyBean[])
	 *
	 * toBean(jsonURL, new TypeReference<Map<String, Map<String, MyBean>>(){})
	 *

	 *
	 * @param jsonURL json url
	 * @param valueTypeRef value type ref
	 * @param <T> t
	 * @return bean
	 */
	public static <T> T toBean(URL jsonURL, TypeReference<T> valueTypeRef) {
		if (valueTypeRef == null || jsonURL == null)
			return null;
		return toBean(new MyJsonParser(jsonURL), valueTypeRef);

	}

	/**
	 * Json string to java bean

	 *

	 * List,Array,Map
	 *

	 *

	 * clazz= new TypeReference<List<MyBean>>(){};
	 *
	 * e.g:
	 * toBean(jsonFile,new TypeReference<List<MyBean>>(){})
	 *
	 * toBean(jsonFile, MyBean[])
	 *
	 * toBean(jsonFile, new TypeReference<Map<String, Map<String, MyBean>>(){})
	 *

	 *
	 * @param jsonFile josn file
	 * @param valueTypeRef value type ref
	 * @param <T> t
	 * @return bean
	 */
	public static <T> T toBean(File jsonFile, TypeReference<T> valueTypeRef) {
		if (valueTypeRef == null || jsonFile == null)
			return null;
		return toBean(new MyJsonParser(jsonFile), valueTypeRef);

	}

	/**
	 * Json string to java bean

	 *

	 * call {@link MyJsonParser#getJsonParser()} return a JsonParser
	 *

	 *
	 * @param myJsonParser custom json parser
	 * @param valueTypeRef value type ref
	 * @see #toBean(JsonParser, TypeReference)
	 * @param <T> t
	 * @return bean
	 */
	protected static <T> T toBean(MyJsonParser myJsonParser,
			TypeReference<T> valueTypeRef) {
		if (myJsonParser.getJsonParser() == null)
			return null;
		return toBean(myJsonParser.getJsonParser(), valueTypeRef);
	}

	/**
	 * Json string to java bean

	 *

	 * List,Array,Map
	 *

	 *

	 * clazz= new TypeReference<List<MyBean>>(){};
	 *
	 * e.g:
	 * toBean(jsonParser,new TypeReference<List<MyBean>>(){})
	 *
	 * toBean(jsonParser, MyBean[])
	 *
	 * toBean(jsonParser, new TypeReference<Map<String, Map<String, MyBean>>(){})
	 *

	 *
	 * @param jsonParser json parser
	 * @param valueTypeRef value type ref
	 * @param <T> t
	 * @return bean
	 */
	public static <T> T toBean(JsonParser jsonParser,
			TypeReference<T> valueTypeRef) {
		if (valueTypeRef == null || jsonParser == null)
			return null;

		T obj = null;
		try {
			obj = getMapper().readValue(jsonParser, valueTypeRef);
		} catch (JsonParseException e) {
			log.error("{}", e.getMessage(), e);
		} catch (JsonMappingException e) {
			log.error("{}", e.getMessage(), e);
		} catch (IOException e) {
			log.error("{}", e.getMessage(), e);
		} finally {
			try {
				jsonParser.close();
			} catch (IOException e) {
			}
		}
		return obj;
	}

	/**
	 * Json string to java bean

	 *

	 * e.g:
	 *

	 *

	 * {"id" : idValue, "name" : nameValue, "aBean" : {"aBeanId" : aBeanIdValue, ...}}
	 *

	 *

	 * List,Array,Map... see {@link #toBean(String, TypeReference)}
	 *

	 *
	 * @param jsonStr json String
	 * @param clazz class
	 * @param <T> t
	 * @return bean
	 */
	public static <T> T toBean(String jsonStr, Class<T> clazz) {
		if (clazz == null || jsonStr == null)
			return null;
		return toBean(new MyJsonParser(jsonStr), clazz);

	}

	/**
	 * Json string to java bean

	 *

	 * e.g:
	 *

	 *

	 * {"id" : idValue, "name" : nameValue, "aBean" : {"aBeanId" : aBeanIdValue, ...}}
	 *

	 *

	 * List,Array,Map... see {@link #toBean(byte[], TypeReference)}
	 *

	 *
	 * @param jsonBytes josn bytes
	 * @param clazz class
	 * @param <T> t
	 * @return bean
	 */
	public static <T> T toBean(byte[] jsonBytes, Class<T> clazz) {
		if (clazz == null || jsonBytes == null)
			return null;
		return toBean(new MyJsonParser(jsonBytes), clazz);

	}

	/**
	 * Json string to java bean

	 *

	 * e.g:
	 *

	 *

	 * {"id" : idValue, "name" : nameValue, "aBean" : {"aBeanId" : aBeanIdValue, ...}}
	 *

	 *

	 * List,Array,Map... see {@link #toBean(Reader, TypeReference)}
	 *

	 *
	 * @param jsonReader json reader
	 * @param clazz class
	 * @param <T> t
	 * @return bean
	 */
	public static <T> T toBean(Reader jsonReader, Class<T> clazz) {
		if (clazz == null || jsonReader == null)
			return null;
		return toBean(new MyJsonParser(jsonReader), clazz);

	}

	/**
	 * Json string to java bean

	 *

	 * e.g:
	 *

	 *

	 * {"id" : idValue, "name" : nameValue, "aBean" : {"aBeanId" : aBeanIdValue, ...}}
	 *

	 *

	 * List,Array,Map... see {@link #toBean(URL, TypeReference)}
	 *

	 *
	 * @param jsonURL josn url
	 * @param clazz class
	 * @param <T> t
	 * @return bean
	 */
	public static <T> T toBean(URL jsonURL, Class<T> clazz) {
		if (clazz == null || jsonURL == null)
			return null;
		return toBean(new MyJsonParser(jsonURL), clazz);

	}

	/**
	 * Json string to java bean

	 *

	 * e.g:
	 *

	 *

	 * {"id" : idValue, "name" : nameValue, "aBean" : {"aBeanId" : aBeanIdValue, ...}}
	 *

	 *

	 * List,Array,Map... see {@link #toBean(File, TypeReference)}
	 *

	 *
	 * @param jsonFile json file
	 * @param clazz class
	 * @param <T> t
	 * @return bean
	 */
	public static <T> T toBean(File jsonFile, Class<T> clazz) {
		if (clazz == null || jsonFile == null)
			return null;
		return toBean(new MyJsonParser(jsonFile), clazz);

	}

	/**
	 * Json string to java bean

	 *

	 * call {@link MyJsonParser#getJsonParser()} return a JsonParser
	 *

	 *
	 * @param myJsonParser custom json parser
	 * @param clazz class
	 * @see #toBean(JsonParser, Class)
	 * @param <T> t
	 * @return bean
	 */
	protected static <T> T toBean(MyJsonParser myJsonParser, Class<T> clazz) {
		if (myJsonParser.getJsonParser() == null)
			return null;
		return toBean(myJsonParser.getJsonParser(), clazz);
	}

	/**
	 * Json string to java bean

	 *

	 * e.g:
	 *

	 *

	 * {"id" : idValue, "name" : nameValue, "aBean" : {"aBeanId" : aBeanIdValue, ...}}
	 *

	 *

	 * List,Array,Map... see {@link #toBean(String, TypeReference)}
	 *

	 *
	 * @param jsonParser json parser
	 * @param clazz class
	 * @param <T> t
	 * @return bean
	 */
	public static <T> T toBean(JsonParser jsonParser, Class<T> clazz) {
		if (clazz == null || jsonParser == null)
			return null;

		T obj = null;
		try {
			obj = getMapper().readValue(jsonParser, clazz);
		} catch (JsonParseException e) {
			log.error("{}", e.getMessage(), e);
		} catch (JsonMappingException e) {
			log.error("{}", e.getMessage(), e);
		} catch (IOException e) {
			log.error("{}", e.getMessage(), e);
		} finally {
			try {
				jsonParser.close();
			} catch (IOException e) {
			}
		}
		return obj;

	}

	/**
	 * Bean to json string
	 *
	 * @param obj obj
	 *            bean object
	 * @param <T> t
	 * @return json string
	 */
	public static <T> String toJson(T obj) {
		StringWriter writer = new StringWriter();
		String jsonStr = "";
		JsonGenerator gen = null;
		try {
			gen = getJsonFactory().createGenerator(writer);
			getMapper().writeValue(gen, obj);
			writer.flush();
			jsonStr = writer.toString();

		} catch (IOException e) {
			log.error("{}", e.getMessage(), e);
		} finally {
			if (gen != null) {
				try {
					gen.close();
				} catch (IOException e) {
				}
			}

		}
		return jsonStr;
	}

	/**
	 * JsonParser Helper
 provide to
	 * {@link JsonUtil#toBean(MyJsonParser, Class)} and
	 * {@link JsonUtil#toBean(MyJsonParser, TypeReference)}
	 */
	protected static class MyJsonParser {

		// ~ Instance fields ==================================================

		/**
		 * JsonParser
		 */
		private JsonParser jsonParser;

		// ~ Constructors ==================================================

		/**
		 * Set jsonParser from {@link JsonFactory#createParser(File)}
		 *
		 * @param obj obj
		 */
		public MyJsonParser(File obj) {
			try {
				this.jsonParser = getJsonFactory().createParser(obj);
			} catch (JsonParseException e) {
				log.error("{}", e.getMessage(), e);
			} catch (IOException e) {
				log.error("{}", e.getMessage(), e);
			}
		}

		/**
		 * Set jsonParser from {@link JsonFactory#createParser(Reader)}
		 *
		 * @param obj obj
		 */
		public MyJsonParser(Reader obj) {
			try {
				this.jsonParser = getJsonFactory().createParser(obj);
			} catch (JsonParseException e) {
				log.error("{}", e.getMessage(), e);
			} catch (IOException e) {
				log.error("{}", e.getMessage(), e);
			}
		}

		/**
		 * Set jsonParser from {@link JsonFactory#createParser(byte[])}
		 *
		 * @param obj obj
		 */
		public MyJsonParser(byte[] obj) {
			try {
				this.jsonParser = getJsonFactory().createParser(obj);
			} catch (JsonParseException e) {
				log.error("{}", e.getMessage(), e);
			} catch (IOException e) {
				log.error("{}", e.getMessage(), e);
			}
		}

		/**
		 * Set jsonParser from {@link JsonFactory#createParser(String)}
		 *
		 * @param obj obj
		 */
		public MyJsonParser(String obj) {
			try {
				this.jsonParser = getJsonFactory().createParser(obj);
			} catch (JsonParseException e) {
				log.error("{}", e.getMessage(), e);
			} catch (IOException e) {
				log.error("{}", e.getMessage(), e);
			}
		}

		/**
		 * Set jsonParser from {@link JsonFactory#createParser(URL)}
		 *
		 * @param obj obj
		 */
		public MyJsonParser(URL obj) {
			try {
				this.jsonParser = getJsonFactory().createParser(obj);
			} catch (JsonParseException e) {
				log.error("{}", e.getMessage(), e);
			} catch (IOException e) {
				log.error("{}", e.getMessage(), e);
			}
		}

		/**
		 * Set jsonParser from {@link JsonFactory#createParser(InputStream)}
		 *
		 * @param obj obj
		 */
		public MyJsonParser(InputStream obj) {
			try {
				this.jsonParser = getJsonFactory().createParser(obj);
			} catch (JsonParseException e) {
				log.error("{}", e.getMessage(), e);
			} catch (IOException e) {
				log.error("{}", e.getMessage(), e);
			}
		}

		// ~ Methods ==================================================

		/**
		 * Return a JsonParser by Constructors
		 *
		 * @return jsonParser
		 */
		public JsonParser getJsonParser() {
			return jsonParser;
		}

	}

}


/*
 * #%L
 * This file is part of a universal JAAS library, providing a universal JDBC
 * authenticator implementation.
 * %%
 * Copyright (C) 2014 - 2016 Michael Beiter <michael@beiter.org>
 * %%
 * All rights reserved.
 * .
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the copyright holder nor the names of the
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 * .
 * .
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
 * #L%
 */
package org.beiter.michael.authn.jaas.loginmodules.password.authenticators.jdbc;

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

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * This class provides utility methods to close JDBC resources.
 */
public final class DbUtil {

    /**
     * The logger object for this class
     */
    private static final Logger LOG = LoggerFactory.getLogger(DbUtil.class);

    /**
     * A private constructor to prevent instantiation of this class
     */
    private DbUtil() {
    }

    /**
     * Close a {@code Connection} and log any SQLExceptions that occur.
     *
     * @param conn Connection to close (may be {@code null})
     */
    public static void close(final Connection conn) {
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                final String error = "Error closing JDBC connection. This may indicate a resource leak.";
                LOG.warn(error, e);
            }
        }
    }

    /**
     * Close a {@code PreparedStatement} and log any SQLExceptions that occur.
     *
     * @param statement PreparedStatement to close (may be {@code null})
     */
    public static void close(final PreparedStatement statement) {
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                final String error = "Error closing JDBC prepared statement. This may indicate a resource leak.";
                LOG.warn(error, e);
            }
        }
    }

    /**
     * Close a {@code ResultSet} and log any SQLExceptions that occur.
     *
     * @param resultSet ResultSet to close (may be {@code null})
     */
    public static void close(final ResultSet resultSet) {
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                final String error = "Error closing JDBC result set. This may indicate a resource leak.";
                LOG.warn(error, e);
            }
        }
    }
}


/**
 * Copyright 2013-2014 Guoqiang Chen, Shanghai, China. All rights reserved.
 *
 * Email: subchen@gmail.com
 * URL: http://subchen.github.io/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package jetbrick.ioc.objects;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.*;
import jetbrick.io.config.Configuration;
import jetbrick.ioc.Ioc;
import jetbrick.ioc.annotations.*;
import jetbrick.ioc.injectors.*;
import jetbrick.ioc.injectors.FieldInjector.FieldContext;
import jetbrick.ioc.injectors.ParameterInjector.ParameterContext;
import jetbrick.lang.ExceptionUtils;
import jetbrick.reflect.*;

class IocObjectUtils {

    //---------------------------------------------------------------------------
    // @Inject 标注的构造函数
    public static CtorInjector doGetCtorInjector(Ioc ioc, KlassInfo klass) {
        ConstructorInfo found = null;

        // 找到对应的构造函数
        for (ConstructorInfo ctor : klass.getDeclaredConstructors()) {
            Inject ref = ctor.getAnnotation(Inject.class);
            if (ref != null) {
                if (found != null) {
                    throw new IllegalStateException("More than two constructors are annotated as injection points in bean: " + klass);
                }
                found = ctor;
            }
        }
        if (found == null) {
            return null;
        }

        // 构造函数参数
        ParameterInjector[] injectors = ParameterInjector.EMPTY_ARRAY;
        List<ParameterInfo> parameters = found.getParameters();
        int size = parameters.size();
        if (size > 0) {
            injectors = new ParameterInjector[size];
            for (int i = 0; i < size; i++) {
                ParameterInfo parameter = parameters.get(i);

                Class<?> parameterInjectorClass = DefaultParameterInjector.class;
                Annotation parameterAnnotation = null;
                // 查找 @Inject/@Config 等标注
                for (Annotation annotation : parameter.getAnnotations()) {
                    InjectParameterWith with = annotation.annotationType().getAnnotation(InjectParameterWith.class);
                    if (with != null) {
                        parameterInjectorClass = with.value();
                        parameterAnnotation = annotation;
                        break;
                    }
                }
                try {
                    injectors[i] = (ParameterInjector) parameterInjectorClass.newInstance();
                    ParameterContext ctx = new ParameterContext(ioc, klass, parameter, parameterAnnotation);
                    injectors[i].initialize(ctx);
                } catch (Exception e) {
                    throw ExceptionUtils.unchecked(e);
                }
            }
        }

        //
        return new CtorInjector(found, injectors);
    }

    // @Inject/@Config 等标注的字段
    public static List<FieldInjector> doGetFieldInjectors(Ioc ioc, KlassInfo klass) {
        List<FieldInjector> injectors = new ArrayList<FieldInjector>(8);
        for (FieldInfo field : klass.getFields()) {
            for (Annotation annotation : field.getAnnotations()) {
                InjectFieldWith with = annotation.annotationType().getAnnotation(InjectFieldWith.class);
                if (with != null) {
                    try {
                        FieldInjector injector = with.value().newInstance();
                        FieldContext ctx = new FieldContext(ioc, klass, field, annotation);
                        injector.initialize(ctx);
                        injectors.add(injector);
                    } catch (Exception e) {
                        throw ExceptionUtils.unchecked(e);
                    }
                }
            }
        }
        if (injectors.size() == 0) {
            return Collections.emptyList();
        }
        return injectors;
    }

    // 注入配置文件中自定义的属性字段
    public static List<PropertyInjector> doGetPropertyInjectors(Ioc ioc, KlassInfo klass, Configuration properties) {
        if (properties == null || properties.size() == 0) {
            return Collections.emptyList();
        }
        List<PropertyInjector> injectors = new ArrayList<PropertyInjector>();
        for (String name : properties.keySet()) {
            PropertyInfo prop = klass.getProperty(name);
            if (prop == null) {
                throw new IllegalStateException("Property not found: " + klass + "#" + name);
            }
            if (!prop.writable()) {
                throw new IllegalStateException("Property not writable: " + prop);
            }

            Object value;
            Class<?> rawType = prop.getRawType(klass.getType());
            if (List.class.isAssignableFrom(rawType)) {
                value = properties.getValueList(prop.getName(), prop.getRawComponentType(klass.getType(), 0));
            } else {
                value = properties.getValue(prop.getName(), rawType, null);
            }
            injectors.add(new PropertyInjector(prop, value));
        }
        return injectors;
    }

    // @Initialize 标注的函数
    public static Method doGetInitializeMethod(KlassInfo klass) {
        MethodInfo found = null;
        for (MethodInfo method : klass.getMethods()) {
            IocInit ref = method.getAnnotation(IocInit.class);
            if (ref != null) {
                if (found != null) {
                    throw new IllegalStateException("More than two methods are annotated @Initialize in bean: " + klass);
                }
                if (method.getParameterCount() != 0) {
                    throw new IllegalStateException("@Initialize method parameters must be empty.");
                }
                found = method;
            }
        }
        return (found == null) ? null : found.getMethod();
    }
}


/**
 * DefaultContentRect.java
 *
 * Created on 21. 11. 2014, 11:25:00 by burgetr
 */
package org.fit.layout.impl;

import java.awt.Color;

import org.fit.layout.model.Border;
import org.fit.layout.model.ContentRect;
import org.fit.layout.model.GenericTreeNode;
import org.fit.layout.model.Page;
import org.fit.layout.model.Rectangular;
import org.fit.layout.model.Border.Side;
import org.fit.layout.model.Border.Style;

/**
 * A default ContentRect implementation. This class is usually not used
 * directly; the {@link DefaultBox} and {@link DefaultArea} subclasses
 * should be used instead.
 *
 * @author burgetr
 */
public class DefaultContentRect<T extends GenericTreeNode<T>> extends DefaultTreeNode<T> implements ContentRect
{
    private static int nextid = 1;

    private int id;
    private Page page;
    private Rectangular bounds;
    private Color backgroundColor;
    private float underline;
    private float lineThrough;
    private float fontSize;
    private float fontStyle;
    private float fontWeight;
    private boolean backgroundSeparated;

    private Border topBorder;
    private Border bottomBorder;
    private Border leftBorder;
    private Border rightBorder;

    public DefaultContentRect(Class<T> myType)
    {
        super(myType);
        id = nextid++;
        bounds = new Rectangular();
        topBorder = new Border();
        bottomBorder = new Border();
        leftBorder = new Border();
        rightBorder = new Border();
    }

    public DefaultContentRect(Class<T> myType, DefaultContentRect<T> src)
    {
        super(myType);
        id = nextid++;
        page = src.page;
        bounds = new Rectangular(src.bounds);
        backgroundColor = (src.backgroundColor == null) ? null : new Color(src.backgroundColor.getRed(), src.backgroundColor.getGreen(), src.backgroundColor.getBlue());
        underline = src.underline;
        lineThrough = src.lineThrough;
        fontSize = src.fontSize;
        fontWeight= src.fontWeight;
        topBorder = src.topBorder;
        bottomBorder = src.bottomBorder;
        leftBorder = src.leftBorder;
        rightBorder = src.rightBorder;
        backgroundSeparated = src.backgroundSeparated;
    }

    @Override
    public int getId()
    {
        return id;
    }

    public void setId(int id)
    {
        this.id = id;
    }

    @Override
    public Page getPage()
    {
        return page;
    }

    public void setPage(Page page)
    {
        this.page = page;
    }

    @Override
    public Color getBackgroundColor()
    {
        return backgroundColor;
    }

    public void setBackgroundColor(Color backgroundColor)
    {
        this.backgroundColor = backgroundColor;
    }

    @Override
    public boolean isBackgroundSeparated()
    {
        return backgroundSeparated;
    }

    public void setBackgroundSeparated(boolean backgroundSeparated)
    {
        this.backgroundSeparated = backgroundSeparated;
    }

    @Override
    public float getUnderline()
    {
        return underline;
    }

    public void setUnderline(float underline)
    {
        this.underline = underline;
    }

    @Override
    public float getLineThrough()
    {
        return lineThrough;
    }

    public void setLineThrough(float lineThrough)
    {
        this.lineThrough = lineThrough;
    }

    @Override
    public float getFontSize()
    {
        return fontSize;
    }

    public void setFontSize(float fontSize)
    {
        this.fontSize = fontSize;
    }

    @Override
    public float getFontStyle()
    {
        return fontStyle;
    }

    public void setFontStyle(float fontStyle)
    {
        this.fontStyle = fontStyle;
    }

    @Override
    public float getFontWeight()
    {
        return fontWeight;
    }

    public void setFontWeight(float fontWeight)
    {
        this.fontWeight = fontWeight;
    }

    @Override
    public int getTopBorder()
    {
        return topBorder.getWidth();
    }

    public void setTopBorder(int width)
    {
        topBorder.setWidth(width);
        if (topBorder.getStyle() == Style.NONE)
            topBorder.setStyle(Style.SOLID);
    }

    @Override
    public int getBottomBorder()
    {
        return bottomBorder.getWidth();
    }

    public void setBottomBorder(int width)
    {
        bottomBorder.setWidth(width);
        if (bottomBorder.getStyle() == Style.NONE)
            bottomBorder.setStyle(Style.SOLID);
    }

    @Override
    public int getLeftBorder()
    {
        return leftBorder.getWidth();
    }

    public void setLeftBorder(int width)
    {
        leftBorder.setWidth(width);
        if (leftBorder.getStyle() == Style.NONE)
            leftBorder.setStyle(Style.SOLID);
    }

    @Override
    public int getRightBorder()
    {
        return rightBorder.getWidth();
    }

    public void setRightBorder(int width)
    {
        rightBorder.setWidth(width);
        if (rightBorder.getStyle() == Style.NONE)
            rightBorder.setStyle(Style.SOLID);
    }

    @Override
    public boolean hasTopBorder()
    {
        return topBorder.getStyle() != Style.NONE;
    }

    @Override
    public boolean hasBottomBorder()
    {
        return bottomBorder.getStyle() != Style.NONE;
    }

    @Override
    public boolean hasLeftBorder()
    {
        return leftBorder.getStyle() != Style.NONE;
    }

    @Override
    public boolean hasRightBorder()
    {
        return rightBorder.getStyle() != Style.NONE;
    }

    /**
     * Sets all the border values.
     * @param top
     * @param right
     * @param bottom
     * @param left
     */
    public void setBorders(int top, int right, int bottom, int left)
    {
        setTopBorder(top);
        setRightBorder(right);
        setBottomBorder(bottom);
        setLeftBorder(left);
    }

    @Override
    public Border getBorderStyle(Side side)
    {
        switch (side)
        {
            case TOP:
                return topBorder;
            case LEFT:
                return leftBorder;
            case BOTTOM:
                return bottomBorder;
            case RIGHT:
                return rightBorder;
        }
        return null;
    }

    public void setBorderStyle(Side side, Border style)
    {
        switch (side)
        {
            case TOP:
                topBorder = new Border(style);
                break;
            case LEFT:
                leftBorder = new Border(style);
                break;
            case BOTTOM:
                bottomBorder = new Border(style);
                break;
            case RIGHT:
                rightBorder = new Border(style);
                break;
        }
    }

    @Override
    public Rectangular getBounds()
    {
        return bounds;
    }

    public void setBounds(Rectangular bounds)
    {
        this.bounds = bounds;
    }

    @Override
    public int getBorderCount()
    {
        int bcnt = 0;
        if (hasTopBorder()) bcnt++;
        if (hasBottomBorder()) bcnt++;
        if (hasLeftBorder()) bcnt++;
        if (hasRightBorder()) bcnt++;
        return bcnt;
    }

    @Override
    public int getX1()
    {
        return getBounds().getX1();
    }

    @Override
    public int getY1()
    {
        return getBounds().getY1();
    }

    @Override
    public int getX2()
    {
        return getBounds().getX2();
    }

    @Override
    public int getY2()
    {
        return getBounds().getY2();
    }

    @Override
    public int getWidth()
    {
        return getBounds().getWidth();
    }

    @Override
    public int getHeight()
    {
        return getBounds().getHeight();
    }

    @Override
    public void move(int xofs, int yofs)
    {
        getBounds().move(xofs, yofs);
        for (T child : getChildren())
        {
            if (child instanceof ContentRect)
                ((ContentRect) child).move(xofs, yofs);
        }
    }

    @Override
    public int hashCode()
    {
        return id;
    }

    @Override
    public boolean equals(Object obj)
    {
        if (this == obj) return true;
        if (obj == null) return false;
        if (getClass() != obj.getClass()) return false;
        @SuppressWarnings("unchecked")
        DefaultContentRect<T> other = (DefaultContentRect<T>) obj;
        if (id != other.id) return false;
        return true;
    }

    public static void resetId()
    {
        nextid = 1;
    }

}


/**
 * Copyright 2013-2014 Guoqiang Chen, Shanghai, China. All rights reserved.
 *
 * Email: subchen@gmail.com
 * URL: http://subchen.github.io/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package jetbrick.reflect;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Type;
import jetbrick.lang.ExceptionUtils;
import jetbrick.reflect.asm.ASMAccessor;

/**
 * 代表一个构造函数.
 *
 * @author Guoqiang Chen
 */
public final class ConstructorInfo extends Executable implements Creater, Comparable<ConstructorInfo> {
    private final KlassInfo declaringKlass;
    private final Constructor<?> constructor;
    private final int offset;

    /**
     * 将 Constructor 对象转成 ConstructorInfo 对象.
     * @param constructor - 原始对象
     * @return ConstructorInfo 对象
     */
    public static ConstructorInfo create(Constructor<?> constructor) {
        KlassInfo klass = KlassInfo.create(constructor.getDeclaringClass());
        return klass.getDeclaredConstructor(constructor);
    }

    protected ConstructorInfo(KlassInfo declaringKlass, Constructor<?> constructor, int offset) {
        this.declaringKlass = declaringKlass;
        this.constructor = constructor;
        this.offset = offset;
        constructor.setAccessible(true);
    }

    @Override
    public KlassInfo getDeclaringKlass() {
        return declaringKlass;
    }

    @Override
    public String getName() {
        return "<init>";
    }

    public Constructor<?> getConstructor() {
        return constructor;
    }

    @Override
    public int getOffset() {
        return offset;
    }

    @Override
    public int getParameterCount() {
        return constructor.getParameterTypes().length;
    }

    @Override
    public Class<?>[] getParameterTypes() {
        return constructor.getParameterTypes();
    }

    @Override
    public Type[] getGenericParameterTypes() {
        return constructor.getGenericParameterTypes();
    }

    public boolean isDefault() {
        return constructor.getParameterTypes().length == 0;
    }

    @Override
    public boolean isVarArgs() {
        return constructor.isVarArgs();
    }

    @Override
    public Annotation[] getAnnotations() {
        return constructor.getAnnotations();
    }

    @Override
    public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
        return constructor.getAnnotation(annotationClass);
    }

    @Override
    public <T extends Annotation> boolean isAnnotationPresent(Class<T> annotationClass) {
        return constructor.isAnnotationPresent(annotationClass);
    }

    @Override
    public Annotation[][] getParameterAnnotations() {
        return constructor.getParameterAnnotations();
    }

    @Override
    public int getModifiers() {
        return constructor.getModifiers();
    }

    @Override
    public Object newInstance(Object... args) {
        ASMAccessor accessor = declaringKlass.getASMAccessor();
        if (accessor == null) {
            try {
                return constructor.newInstance(args);
            } catch (Exception e) {
                throw ExceptionUtils.unchecked(e);
            }
        } else {
            return accessor.newInstance(offset, args);
        }
    }

    @Override
    public int compareTo(ConstructorInfo o) {
        return getSignature().compareTo(o.getSignature());
    }
}


package com.w3asel.cubesensors.util;

import org.scribe.builder.ServiceBuilder;
import org.scribe.model.SignatureType;
import org.scribe.model.Token;
import org.scribe.model.Verifier;
import org.scribe.oauth.OAuthService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.w3asel.cubesensors.CubeSensorsProperties;
import com.w3asel.cubesensors.api.v1.CubeSensorsApiV1;
import com.w3asel.cubesensors.api.v1.CubeSensorsException;
import com.w3asel.cubesensors.auth.CubeSensorsAuthApi;

/**
 * A utility class used to simplify the authorization using persistence for
 * an authorized request token.
 * If no persisted token found it will initiate the authorization, code provided using the console.
 *

 * Usage with default providers:
 *

 * Token accessToken = CubeSensorsUtils.instance().getAccessToken();
 * CubeSensorsApiV1 api = new CubeSensorsApiV1(accessToken);
 * api.getDevices();
 *

 *
Or assemble a CubeSensorsUtils setting a custom AuthPersistence or AuthProvider:
 *

 *
 * CubeSensorsUtils u = new CubeSensorsUtils();
 * u.setAuthProvider(... custom auth provider ...)
 * u.setAuthPersistence(... custom persistence ...)
 * Token accessToken = u.getAccessToken();
 * CubeSensorsApiV1 api = new CubeSensorsApiV1(accessToken);
 * api.getDevices();
 *
 *

 *
 * @author Silviu Marcu
 *
 */
public class CubeSensorsUtils {

	private static final Logger LOGGER = LoggerFactory.getLogger(CubeSensorsUtils.class);

	private AuthPersistence authPersistence;
	private AuthProvider authProvider;

	/**
	 * Creates a new util object
	 * @param authPersistence the {@link AuthPersistence} implementation to be used in the util object
	 * @param authProvider the {@link AuthProvider} implementation to be used in the util object
	 */
	public CubeSensorsUtils(AuthPersistence authPersistence, AuthProvider authProvider) {
		this.authPersistence = authPersistence;
		this.authProvider = authProvider;
	}

	/**
	 * Obtain an access token. If previously a token was created and persisted
	 * will be returned after validation (a real call is made to validate).
	 *
If no token previously persisted, the method will create a new token using
	 * the authentication provider (AuthProvider)
	 * @return the access token.
	 */
	public Token getAccessToken() {

		Token accessToken = authPersistence.getToken();

		if (isTokenValid(accessToken)) {
			return accessToken;
		}

		// authorize
		accessToken = authorize();

		// save
		authPersistence.saveToken(accessToken);

		return accessToken;
	}

	private Token authorize() {
		OAuthService service = new ServiceBuilder()
				.provider(CubeSensorsAuthApi.class)
				.apiKey(CubeSensorsProperties.getAppKey())
				.apiSecret(CubeSensorsProperties.getAppSecret())
				.signatureType(SignatureType.QueryString).build();

		Token requestToken = service.getRequestToken();
		String authorizationUrl = service.getAuthorizationUrl(requestToken);

		String authorization = authProvider.getAuthorization(authorizationUrl);

		Token accessToken = service.getAccessToken(requestToken, new Verifier(
				authorization));

		return accessToken;
	}

	private boolean isTokenValid(Token token) {
		if (token != null) {
			// try a real call to verify the access
			CubeSensorsApiV1 api = new CubeSensorsApiV1(token);
			// throws CubeSensorsException if not authorized
			try {
				api.getDevices();
				return true;
			} catch (CubeSensorsException e) {
				if (e.getMessage().contains("401")) {
					LOGGER.error("Unauthorized, reauthorizing", e);
	        	} else {
	        		LOGGER.error("cannot validate request token", e);
	        	}
			}
		}
		return false;
	}

	/**
	 * Inject an AuthPersistence implementation.
	 * @param authPersistence the implementation to be injected
	 */
	public void setAuthPersistence(AuthPersistence authPersistence) {
		this.authPersistence = authPersistence;
	}

	/**
	 * Inject an AuthProvider implementation
	 * @param authProvider the implementation object
	 */
	public void setAuthProvider(AuthProvider authProvider) {
		this.authProvider = authProvider;
	}

	/**
	 * Creates a new instance of {@link CubeSensorsUtils} using {@link PrefAuthPersistence}
	 * as {@link AuthPersistence} and {@link ConsoleAuthProvider} as {@link AuthProvider}
	 * @return the assembled utils object
	 */
	public static CubeSensorsUtils instance() {
		CubeSensorsUtils utils = new CubeSensorsUtils(new PrefAuthPersistence(), new ConsoleAuthProvider());
		return utils;
	}
}