public class FlyFactory {

	public static PeriodWork getPeriodWork(){
		Jenkins jenkins = Jenkins.getInstance();
		ExtensionList<PeriodWork> extensionList  = jenkins.getExtensionList(PeriodWork.class);
		PeriodWork periodWork = extensionList.get(PeriodWork.class);
		return periodWork;
	}
	
	public static DeployInfo getDeployInfo(){
		Jenkins jenkins = Jenkins.getInstance();
		ExtensionList<DeployInfo> extensionList  = jenkins.getExtensionList(DeployInfo.class);
		DeployInfo deployInfo = extensionList.get(DeployInfo.class);
		return deployInfo;
	}
	
	public static IncreaseIndexer getIncreaseIndexer(){
		return IncreaseIndexer.getInstance();
	}
	
	public static Map<String, Object> getPropertiesOfJob(String name){
		Jenkins jenkins = Jenkins.getInstance();
	
		List<Item> itemList = jenkins.getAllItems();
	
		for(Item item : itemList){
			for(Job job : item.getAllJobs()){
				if(name.equals(job.getName())){
					return job.getProperties();
				}
			}
		}
		return null;
	}
	
	
	public static NetworkSpace getNetworkSpace(){
		return NetworkSpace.getInstance();
	}
	
	
	public static String getRootPathOfJob(String name){
		Jenkins jenkins = Jenkins.getInstance();
		List<Item> itemList = jenkins.getAllItems();
		for(Item item : itemList){
			for(Job job : item.getAllJobs()){
				if(name.equals(job.getName())){
					return job.getRootDir().getAbsolutePath();
				}
			}
		}
		return null;
	}
}
 public class AgentService {
	/**
	 * agent id
	 */
	private int agentId;
	
	/**
	 * host of agent  
	 */
	private String host;
	
	/**
	 * state of agent 
	 */
	private boolean isRun = false;
	
	
	/***
	 * service meta info List
	 */
	private List<ServiceMeta> serviceMetaList;
	
	public int getAgentId() {
		return agentId;
	}

	public void setAgentId(int agentId) {
		this.agentId = agentId;
	}

	public String getHost() {
		return host;
	}

	public void setHost(String host) {
		this.host = host;
	}

	public boolean isRun() {
		return isRun;
	}

	public void setRun(boolean isRun) {
		this.isRun = isRun;
	}

	public List<ServiceMeta> getServiceMetaList() {
		return serviceMetaList;
	}

	public void setServiceMetaList(List<ServiceMeta> serviceMetaList) {
		this.serviceMetaList = serviceMetaList;
	}
} public class ServiceGroup {
	/**
	 * Service 의 Group Id
	 */
	private int groupId;
	
	/**
	 * Service Group Name;
	 */
	private String groupName;
	
	
	private List<ServiceMeta> serviceMetaList = null;
	
	public int getGroupId() {
		return groupId;
	}

	public void setGroupId(int groupId) {
		this.groupId = groupId;
	}

	public String getGroupName() {
		return groupName;
	}

	public void setGroupName(String groupName) {
		this.groupName = groupName;
	}

	public List<ServiceMeta> getServiceMetaList() {
		return serviceMetaList;
	}

	public void setServiceMetaList(List<ServiceMeta> serviceMetaList) {
		this.serviceMetaList = serviceMetaList;
	}
	
	
} public class ServiceMeta {
	
	/**
	 *  Service Server host
	 */
	private String host;
	/**
	 * deploy destination point
	 */
	private String destination;
	
	/**
	 * deploy type
	 */
	private Integer type;
	
	/**
	 * Service Server Group Id 
	 */
	private Integer groupId;
	
	/**
	 * Service Server Id (auto increase) 
	 */
	private Integer serviceId;
	/**
	 * test cmd after deploy 
	 */
	private String command;
	
	/**
	 * priority of deployment  
	 */
	private Integer weight;
	/**
	 * process id of service app
	 */
	private Integer pid;
	
	/**
	 * process id of service name
	 */
	private String name;
	
	
	/**
	 * test url info
	 */
	private String testUrl;


	/**
	 * install able
	 */
	private boolean installAble;

	
	private int dependenceService =0 ;
	
	
	

	public String getHost() {
		return host;
	}

	public void setHost(String host) {
		this.host = host;
	}


	public String getDestination() {
		return destination;
	}


	public void setDestination(String destination) {
		this.destination = destination;
	}


	public Integer getType() {
		return type;
	}


	public void setType(Integer type) {
		this.type = type;
	}


	public Integer getGroupId() {
		if(groupId == null)
			return 0;
		return groupId;
	}


	public void setGroupId(Integer groupId) {
		this.groupId = groupId;
	}


	public Integer getServiceId() {
		if(this.serviceId == null)
			return 0;
		
		return this.serviceId;
	}


	public void setServiceId(Integer serviceId) {
		this.serviceId = serviceId;
	}


	public String getCommand() {
		return command;
	}


	public void setCommand(String command) {
		this.command = command;
	}


	public Integer getWeight() {
		return weight;
	}


	public void setWeight(Integer weight) {
		this.weight = weight;
	}


	public Integer getPid() {
		if(pid == null)
			return 0;
		return pid;
	}


	public void setPid(Integer pid) {
		this.pid = pid;
	}


	public String getName() {
		return name;
	}


	public void setName(String name) {
		this.name = name;
	}


	public String getTestUrl() {
		return testUrl;
	}


	public void setTestUrl(String testUrl) {
		this.testUrl = testUrl;
	}


	public boolean isInstallAble() {
		return installAble;
	}


	public void setInstallAble(boolean installAble) {
		this.installAble = installAble;
	}
	
	public int getDependenceService() {
		return dependenceService;
	}

	public void setDependenceService(int dependenceService) {
		this.dependenceService = dependenceService;
	}

} public class NetworkSpace {
	/**
	 * singleton Instance
	 */
	private static NetworkSpace networkSpace = new NetworkSpace();
	
	private Map<String, List<AgentService>> networkMap = new ConcurrentHashMap<String, List<AgentService>>();
	
	private Map<String, List<InstanceModel>> instanceModelMap = new ConcurrentHashMap<String, List<InstanceModel>>();
	
	private NetworkSpace(){ }
	
	public static NetworkSpace getInstance(){
		return networkSpace;
	}
	/**
	 * initialization network space
	 */
	public void initNetwork(){
		List<ServiceMeta> serviceMetaList = ServiceGroupSaveableUtil.getServiceMetaList();
		processInitNetwork(serviceMetaList);
	}
	
	
	/**
	 * attach service meta into network space
	 * @param serviceMeta
	 */
	public void attachServiceMeta(ServiceMeta serviceMeta){
		List<ServiceMeta> serviceMetaList = new ArrayList<ServiceMeta>();
		serviceMetaList.add(serviceMeta);
		processInitNetwork(serviceMetaList);
	}
	
	
	public ServiceMeta getServiceMeta(String host, int serviceId){
		List<AgentService> agentServiceList = this.getAgentListByHost(host);
		for(AgentService agentService : agentServiceList){
			List<ServiceMeta> serviceMetaList = agentService.getServiceMetaList();
			for(ServiceMeta serviceMeta : serviceMetaList){
				if(serviceId == serviceMeta.getServiceId())
					return serviceMeta;
			}
		}
		return null;
	}
	
	public ServiceMeta getServiceMeta(int serviceId){
		for(String host : networkMap.keySet()){
			ServiceMeta serviceMeta = getServiceMeta(host, serviceId);
			if(serviceMeta != null)
				return serviceMeta;
		}
		return null;
	}
	
	public List<ServiceMeta> getServiceMetaList(){
		List<AgentService> agentServiceList = getAgentServiceList();
		List<ServiceMeta> resultList = new ArrayList<ServiceMeta>();
		for(AgentService agentService : agentServiceList){
			List<ServiceMeta> serviceMetaList = agentService.getServiceMetaList();
			if(serviceMetaList != null)
				resultList.addAll(serviceMetaList);
		}
		return resultList;
	}
	
	/**
	 * obtain agent of service list 
	 * @param host
	 * @return List<AgentService>
	 */
	public List<AgentService> getAgentListByHost(String host){
		if(networkMap.containsKey(host)){
			return networkMap.get(host);
		}
		return Collections.EMPTY_LIST;
	}
	
	public Map<String, List<AgentService>> getNetworkMap(){
		return networkMap;
	}
	
	public List<AgentService> getAgentServiceList(){
		if(networkMap.size() == 0)
			return Collections.EMPTY_LIST;
		
		List<AgentService> agentServiceList = new ArrayList<AgentService>(); 
		for(List<AgentService> partAgentServiceList : networkMap.values()){
			agentServiceList.addAll(partAgentServiceList);
		}
		return agentServiceList;
	}
	
	public Map<String, List<InstanceModel>> getInstanceModelMap(){
		return instanceModelMap;
	}
	
	public void reload(){
		this.networkMap.clear();
		this.instanceModelMap.clear();
		this.initNetwork();
	}
	
	private void processInitNetwork(List<ServiceMeta> serviceMetaList){
		
		int agentId = networkMap.size() + 1 ;
		for(ServiceMeta serviceMeta : serviceMetaList){
			
			// exist agent in networkMap
			if(networkMap.containsKey(serviceMeta.getHost())){
				List<AgentService> agentServiceList = networkMap.get(serviceMeta.getHost());
				for(AgentService agentService : agentServiceList){
					List<ServiceMeta> agentServiceMetaList = agentService.getServiceMetaList();
					agentServiceMetaList.add(serviceMeta);
					break;
				}
			// don't exist agent in networkMap
			}else{
				// create AgentService List
				List<AgentService> agentServiceList = new ArrayList<AgentService>();
				
				// create meta of service List
				List<ServiceMeta> agentServiceMetaList = new ArrayList<ServiceMeta>();
				// add meta of service into ServiceMeta List
				agentServiceMetaList.add(serviceMeta);

				// create agent service
				AgentService agentService = new AgentService();
				// set id into agent service		
				agentService.setAgentId(agentId);
				// set host into agent service
				agentService.setHost(serviceMeta.getHost());
				// set meta of service into agent service
				agentService.setServiceMetaList(agentServiceMetaList);
				
				//add agent service into agent service list
				agentServiceList.add(agentService);
				
				// add agent service list into network map
				networkMap.put(serviceMeta.getHost(), agentServiceList);
				agentId++;
			}
		}
	}

} public class ServiceGroupSaveable implements Saveable {

	private List<ServiceGroup> serviceGroupList=null;
	private String saveDir = null;
	
	
	/**
	 * save data
	 */
	public void save() throws IOException {
		if(BulkChange.contains(this))   return;
        try {
            getConfigFile().write(this);
            SaveableListener.fireOnChange(this, getConfigFile());
        } catch (IOException e) {
           	e.printStackTrace();
        }
		
	}
	
	protected XmlFile getConfigFile() {
		if(saveDir !=null)
		    return new XmlFile(new File(saveDir, this.getClass().getSimpleName()+".xml"));
	    		
	    return new XmlFile(new File(Jenkins.getInstance().getRootDir(), this.getClass().getSimpleName()+".xml"));
    }
	
	/**
	 * open file and load data
	 */
	 public synchronized void load() {
		 XmlFile file = getConfigFile();
		 if(!file.exists())
			 return;
		 try {
			 file.unmarshal(this);
		 } catch (IOException e) {
			 e.printStackTrace();
		 }
	 }

	public List<ServiceGroup> getServiceGroupList() {
		return serviceGroupList;
	}

	public void setServiceGroupList(List<ServiceGroup> serviceGroupList) {
		this.serviceGroupList = serviceGroupList;
	}

	public String getSaveDir() {
		return saveDir;
	}

	public void setSaveDir(String saveDir) {
		this.saveDir = saveDir;
	}
} public class ServiceGroupSaveableUtil {

	public static ServiceGroup getServiceGroup(int groupId){
		ServiceGroupSaveable serviceGroupSaveable = new ServiceGroupSaveable();
		serviceGroupSaveable.load();
		List<ServiceGroup> serviceGroupList = serviceGroupSaveable.getServiceGroupList();
		
		if(serviceGroupList == null)
			return null;
		
		for(ServiceGroup serviceGroup : serviceGroupList){
			if(serviceGroup.getGroupId() == groupId){
				return serviceGroup;
			}
		}
		return null;
	}
	
	
	public static void saveServiceMeta(ServiceMeta serviceMeta){
		ServiceGroupSaveable serviceGroupSaveable = new ServiceGroupSaveable();
		serviceGroupSaveable.load();
		saveServiceMeta(serviceGroupSaveable, serviceMeta);
	}
	
	public static void delServiceMeta(ServiceMeta serviceMeta){
		ServiceGroupSaveable serviceGroupSaveable = new ServiceGroupSaveable();
		serviceGroupSaveable.load();
		List<ServiceGroup> serviceGroupList = ServiceGroupSaveableUtil.getServiceGroupList(serviceGroupSaveable);
		boolean isDel = false;
		for(ServiceGroup serviceGroup : serviceGroupList){
			List<ServiceMeta> serviceMetaList = serviceGroup.getServiceMetaList();
			
			for(ServiceMeta saveServiceMeta : serviceMetaList){

				if(serviceMeta.getServiceId().equals(saveServiceMeta.getServiceId())){
					serviceMetaList.remove(saveServiceMeta);
					isDel = true;
					break;
				}
			}
			if(isDel){
				serviceGroup.setServiceMetaList(serviceMetaList);
			}
		}
		if(isDel){
			serviceGroupSaveable.setServiceGroupList(serviceGroupList);
			
			try {
				serviceGroupSaveable.save();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	public static void delServiceGroup(int groupId){
		ServiceGroupSaveable serviceGroupSaveable = new ServiceGroupSaveable();
		serviceGroupSaveable.load();
		List<ServiceGroup> serviceGroupList = ServiceGroupSaveableUtil.getServiceGroupList(serviceGroupSaveable);

		boolean isDel = false;
		for(ServiceGroup serviceGroup : serviceGroupList){
			if(serviceGroup.getGroupId() == groupId){
				serviceGroupList.remove(serviceGroup);
				isDel = true;
				break;
			}
		}
		if(isDel){
			serviceGroupSaveable.setServiceGroupList(serviceGroupList);
			try {
				serviceGroupSaveable.save();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	
	/**
	 * save service meta info
	 * @param serviceGroupSaveable
	 * @param serviceMeta
	 */
	public static void saveServiceMeta(ServiceGroupSaveable serviceGroupSaveable, ServiceMeta serviceMeta){
		if(serviceGroupSaveable == null || serviceGroupSaveable.getServiceGroupList() == null)
			return;
		
		if(serviceMeta.getGroupId() == 0)
			return;
		int maxServiceId = 0;
		for(ServiceGroup serviceGroup : serviceGroupSaveable.getServiceGroupList()){
			List<ServiceMeta> serviceMetaList = serviceGroup.getServiceMetaList();
			if(serviceGroup.getGroupId() == serviceMeta.getGroupId()){
				if(serviceMetaList == null){
					serviceMetaList = new ArrayList<ServiceMeta>();
					serviceGroup.setServiceMetaList(serviceMetaList);
				}
				serviceMetaList.add(serviceMeta);
				ModelSoting.serviceSortByWeight(serviceMetaList);
			}
			if(serviceMetaList !=null && serviceMeta.getServiceId() == 0){
				for(ServiceMeta partServiceMeta : serviceMetaList){
					if(maxServiceId < partServiceMeta.getServiceId())
						maxServiceId = partServiceMeta.getServiceId();
				}
			}
		}
		if(serviceMeta.getServiceId() == 0){
			maxServiceId++;
			serviceMeta.setServiceId(maxServiceId);
		}
		
		try {
			serviceGroupSaveable.save();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public static List<ServiceMeta> getServiceMetaList(){
		ServiceGroupSaveable serviceGroupSaveable = new ServiceGroupSaveable();
		serviceGroupSaveable.load();
		return getServiceMetaList(serviceGroupSaveable);
	}
	
	public static List<ServiceMeta> getServiceMetaList(ServiceGroupSaveable serviceGroupSaveable){
		if(serviceGroupSaveable == null || serviceGroupSaveable.getServiceGroupList() == null)
			return Collections.EMPTY_LIST;
		
		List<ServiceMeta> resultServiceMetaList = new ArrayList<ServiceMeta>();
		
		for(ServiceGroup serviceGroup : serviceGroupSaveable.getServiceGroupList()){
			List<ServiceMeta> serviceMetaList = serviceGroup.getServiceMetaList();
			if(serviceMetaList != null){
				resultServiceMetaList.addAll(serviceMetaList);
			}
		}
		return resultServiceMetaList;
	}
	
	public static List<ServiceGroup> getServiceGroupList(){
		ServiceGroupSaveable serviceGroupSaveable = new ServiceGroupSaveable();
		serviceGroupSaveable.load();
		return getServiceGroupList(serviceGroupSaveable);
	}
	
	public static List<ServiceGroup> getServiceGroupList(ServiceGroupSaveable serviceGroupSaveable){
		List<ServiceGroup> serviceGroupList = serviceGroupSaveable.getServiceGroupList();
		if(serviceGroupList == null)
			return Collections.EMPTY_LIST;
		return serviceGroupList;
	}
	
	public static List<ServiceMeta> getServiceMetaListByGroupId(int groupId){
		ServiceGroupSaveable serviceGroupSaveable = new ServiceGroupSaveable();
		serviceGroupSaveable.load();
		return ServiceGroupSaveableUtil.getServiceMetaListByGroupId(groupId, serviceGroupSaveable.getServiceGroupList());
	}
	
	public static List<ServiceMeta> getServiceMetaListByGroupId(int groupId, List<ServiceGroup> serviceGroupList){
		if(serviceGroupList == null)
			return Collections.EMPTY_LIST;
		
		for(ServiceGroup serviceGroup : serviceGroupList){
			if(serviceGroup.getGroupId() == groupId)
				return serviceGroup.getServiceMetaList();
		}
		
		return Collections.EMPTY_LIST;
	}	
	
} public class RequestMap {
	int type;
	Object arg;
	
	public int getType() {
		return type;
	}
	public void setType(int type) {
		this.type = type;
	}
	public Object getArg() {
		return arg;
	}
	public void setArg(Object arg) {
		this.arg = arg;
	}
}
 public class RequestQueue {

	private Map<String, LinkedList<RequestMap>> requestQueueMap = new Hashtable<String, LinkedList<RequestMap>>();

	public LinkedList<RequestMap> getRequest(String host){
		if(requestQueueMap.containsKey(host)){
			return requestQueueMap.get(host);
		}
		return null;
	}
	
	
	public void add(String host, RequestMap requestMap){
		if(requestQueueMap.containsKey(host)){
			requestQueueMap.get(host).add(requestMap);
		}else{
			LinkedList<RequestMap> requestQueue = new LinkedList<RequestMap>();
			requestQueue.add(requestMap);
			requestQueueMap.put(host, requestQueue);
		}
	}
	
}
 @Extension
public class PeriodWork extends PeriodicWork {
	
	private RequestQueue requestQueue = new RequestQueue();
	private DeploySurveillant deploySurveillant = new DeploySurveillant();
	
	public RequestQueue getRequestQueue(){
		return requestQueue;
	}

	public DeploySurveillant getDeploySurveillant(){
		return deploySurveillant;
	}
	
	public Map<String, DeployReport> getDeployReportMap(){
		return deploySurveillant.getDeployReportMap();
	}
	
	@Override
	public long getRecurrencePeriod() {
		//return MIN;
		return 10000;
	}

	@IgnoreJRERequirement
	@Override
	protected void doRun() throws Exception {
		deploySurveillant.process();
	}
}
 public class FlyUser extends UserProperty {
	private final boolean isFlyRoot;
	
	public FlyUser(boolean isFlyRoot){
		this.isFlyRoot = isFlyRoot;
	}

	@Exported
	public boolean getIsFlyRoot(){
		return this.isFlyRoot;
	}
	
	public static boolean isFlyRoot(){
		User user = User.current();
		boolean flyRoot = false;
		if(user!=null && user.getProperty(FlyUser.class).getIsFlyRoot()){
			flyRoot=true;
	    }
		return flyRoot;
	}
	
	 @Extension
	  public static final class DescriptorImpl extends UserPropertyDescriptor {
	        public String getDisplayName() {
	            return "flyRoot";
	        }

	        public UserProperty newInstance(User user) {
	            return new FlyUser(false); 
	        }

	        @Override
	        public UserProperty newInstance(StaplerRequest req, JSONObject formData) throws FormException {
	            return new FlyUser(formData.optBoolean("flyRoot"));
	        }
	    }
}
 public class FlyJenkinsEnv {

	public static String getProductionRoot(){
		return Jenkins.getInstance().getRootDir().getAbsolutePath() + "/flyJenkins/job";
	}
	
	public static String getLastBuildPath(int serviceId){
		return Jenkins.getInstance().getRootDir().getAbsolutePath() + "/flyJenkins/lastBuild/"+serviceId+"/service.zip";
	}
}

import java.io.IOException;
import java.util.Collections;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import com.agun.flyJenkins.FlyFactory;
import com.agun.flyJenkins.model.AgentService;
import com.agun.flyJenkins.model.ServiceGroup;
import com.agun.flyJenkins.model.ServiceMeta;
import com.agun.flyJenkins.network.NetworkSpace;
import com.agun.flyJenkins.persistence.ServiceGroupSaveable;
import com.agun.flyJenkins.persistence.ServiceGroupSaveableUtil;
import com.agun.flyJenkins.request.RequestMap;
import com.agun.flyJenkins.request.RequestQueue;
import com.agun.flyJenkins.schedule.PeriodWork;
import com.agun.flyJenkins.user.FlyUser;
import com.agun.flyJenkins.util.FlyJenkinsEnv;
import hudson.Extension;

package com.agun.flyJenkins.ui;





@Extension
public class ConfigServiceMeta extends FlyUI {

	public ConfigServiceMeta() {}
	
	
	/**
	 * obtain service group list
	 * @return List<ServiceGroup>
	 */

	public List<ServiceGroup> getServiceGroupList(){
