001/* 002 * Copyright 2010-2015 Institut Pasteur. 003 * 004 * This file is part of Icy. 005 * 006 * Icy is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * Icy is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with Icy. If not, see <http://www.gnu.org/licenses/>. 018 */ 019package icy.workspace; 020 021import icy.network.NetworkUtil; 022import icy.network.URLUtil; 023import icy.preferences.RepositoryPreferences; 024import icy.preferences.RepositoryPreferences.RepositoryInfo; 025import icy.system.IcyExceptionHandler; 026import icy.util.StringUtil; 027import icy.util.XMLUtil; 028 029import java.util.ArrayList; 030import java.util.Collections; 031import java.util.EventListener; 032 033import javax.swing.event.EventListenerList; 034 035import org.w3c.dom.Document; 036import org.w3c.dom.Node; 037 038/** 039 * @author Stephane 040 */ 041public class WorkspaceRepositoryLoader 042{ 043 public static interface WorkspaceRepositoryLoaderListener extends EventListener 044 { 045 public void workspaceRepositeryLoaderChanged(); 046 } 047 048 private class LoadRunner extends Thread 049 { 050 public LoadRunner() 051 { 052 super("Online workspace loader"); 053 } 054 055 @Override 056 public void run() 057 { 058 // no Internet connection ? 059 if (!NetworkUtil.hasInternetAccess()) 060 { 061 failed = true; 062 return; 063 } 064 065 final ArrayList<Workspace> newWorkspaces = new ArrayList<Workspace>(); 066 067 failed = false; 068 try 069 { 070 final ArrayList<RepositoryInfo> repositories = RepositoryPreferences.getRepositeries(); 071 072 // load online workspace from all active repositories 073 for (RepositoryInfo repoInfo : repositories) 074 { 075 if (interrupted()) 076 return; 077 078 if (repoInfo.isEnabled()) 079 { 080 final ArrayList<Workspace> workspacesRepos = loadInternal(repoInfo); 081 082 if (workspacesRepos == null) 083 { 084 failed = true; 085 return; 086 } 087 088 newWorkspaces.addAll(workspacesRepos); 089 } 090 } 091 092 // sort list 093 Collections.sort(newWorkspaces); 094 095 synchronized (workspaces) 096 { 097 workspaces = newWorkspaces; 098 } 099 } 100 catch (Exception e) 101 { 102 IcyExceptionHandler.showErrorMessage(e, true); 103 failed = true; 104 return; 105 } 106 107 changed(); 108 } 109 } 110 111 private static final String ID_ROOT = "workspaces"; 112 private static final String ID_WORKSPACE = "workspace"; 113 private static final String ID_PATH = "path"; 114 115 /** 116 * static class 117 */ 118 private static final WorkspaceRepositoryLoader instance = new WorkspaceRepositoryLoader(); 119 120 /** 121 * Online workspace list 122 */ 123 ArrayList<Workspace> workspaces; 124 125 /** 126 * internal 127 */ 128 boolean failed; 129 130 private LoadRunner loadRunner; 131 132 /** 133 * listeners 134 */ 135 private final EventListenerList listeners; 136 137 /** 138 * static class 139 */ 140 private WorkspaceRepositoryLoader() 141 { 142 super(); 143 144 workspaces = new ArrayList<Workspace>(); 145 listeners = new EventListenerList(); 146 failed = false; 147 148 // initial loading 149 startLoad(); 150 } 151 152 /** 153 * Return the workspaces file list from a repository URL 154 */ 155 public static ArrayList<String> getWorkspaceFiles(RepositoryInfo repos) 156 { 157 final ArrayList<String> result = new ArrayList<String>(); 158 final Document document = XMLUtil.loadDocument(repos.getLocation(), repos.getAuthenticationInfo(), true); 159 160 if (document != null) 161 { 162 // get workspaces node 163 final Node workspacesNode = XMLUtil.getElement(document.getDocumentElement(), ID_ROOT); 164 165 // workspaces node found 166 if (workspacesNode != null) 167 { 168 final ArrayList<Node> nodes = XMLUtil.getChildren(workspacesNode, ID_WORKSPACE); 169 170 for (Node node : nodes) 171 { 172 final String path = XMLUtil.getElementValue(node, ID_PATH, ""); 173 174 if (!StringUtil.isEmpty(path)) 175 result.add(path); 176 } 177 } 178 } 179 else 180 { 181 if (!NetworkUtil.hasInternetAccess()) 182 System.out.println("You are not connected to internet."); 183 else 184 System.out.println("Can't access repository '" + repos.getName() + "'"); 185 } 186 187 return result; 188 } 189 190 /** 191 * Start loading process 192 */ 193 private void startLoad() 194 { 195 loadRunner = new LoadRunner(); 196 loadRunner.start(); 197 } 198 199 /** 200 * Reload all online workspaces from all active repositories (old list is cleared) 201 */ 202 public static void reload() 203 { 204 // request interrupt 205 instance.loadRunner.interrupt(); 206 207 // We don't need to wait... can make the preferences panel to lag on validation 208// // wait for end processing 209// try 210// { 211// instance.loadRunner.join(); 212// } 213// catch (InterruptedException e) 214// { 215// // ignore 216// } 217 218 // start it again 219 instance.startLoad(); 220 } 221 222 /** 223 * Load and return the list of online workspaces located at specified repository url 224 */ 225 ArrayList<Workspace> loadInternal(RepositoryInfo repos) 226 { 227 final ArrayList<String> paths = getWorkspaceFiles(repos); 228 229 // error while retrieving paths ? 230 if (paths == null) 231 { 232 if (!NetworkUtil.hasInternetAccess()) 233 System.out.println("You are not connected to internet."); 234 else 235 System.out.println("Can't access repository '" + repos.getName() + "'"); 236 237 return null; 238 } 239 240 final ArrayList<Workspace> result = new ArrayList<Workspace>(); 241 242 for (String path : paths) 243 { 244 try 245 { 246 final Workspace workspace = new Workspace(URLUtil.getURL(path), repos); 247 248 if (!workspace.isEmpty()) 249 result.add(workspace); 250 } 251 catch (Exception e) 252 { 253 System.err.println("WorkspaceRepositoryLoader.load('" + repos.getLocation() + "') error :"); 254 IcyExceptionHandler.showErrorMessage(e, false); 255 } 256 } 257 258 return result; 259 } 260 261 /** 262 * @return the workspaceList 263 */ 264 public static ArrayList<Workspace> getWorkspaces() 265 { 266 synchronized (instance.workspaces) 267 { 268 return new ArrayList<Workspace>(instance.workspaces); 269 } 270 } 271 272 public static Workspace getWorkspace(String className) 273 { 274 synchronized (instance.workspaces) 275 { 276 return Workspace.getWorkspace(instance.workspaces, className); 277 } 278 } 279 280 /** 281 * Return the workspace list from the specified repository 282 */ 283 public static ArrayList<Workspace> getWorkspaces(RepositoryInfo repos) 284 { 285 final ArrayList<Workspace> result = new ArrayList<Workspace>(); 286 287 synchronized (instance.workspaces) 288 { 289 for (Workspace workspace : instance.workspaces) 290 if (workspace.getRepository().equals(repos)) 291 result.add(workspace); 292 } 293 294 return result; 295 } 296 297 /** 298 * @return the loaded 299 */ 300 public static boolean isLoading() 301 { 302 return instance.loadRunner.isAlive(); 303 } 304 305 /** 306 * wait until loading completed 307 */ 308 public static void waitWhileLoading() 309 { 310 try 311 { 312 instance.loadRunner.join(); 313 } 314 catch (InterruptedException e) 315 { 316 // ignore 317 } 318 } 319 320 /** 321 * return true if an error occurred during the workspace loading process 322 */ 323 public static boolean failed() 324 { 325 return instance.failed; 326 } 327 328 /** 329 * workspace list has changed 330 */ 331 void changed() 332 { 333 fireEvent(); 334 } 335 336 /** 337 * Add a listener 338 * 339 * @param listener 340 */ 341 public static void addListener(WorkspaceRepositoryLoaderListener listener) 342 { 343 synchronized (instance.listeners) 344 { 345 instance.listeners.add(WorkspaceRepositoryLoaderListener.class, listener); 346 } 347 } 348 349 /** 350 * Remove a listener 351 * 352 * @param listener 353 */ 354 public static void removeListener(WorkspaceRepositoryLoaderListener listener) 355 { 356 synchronized (instance.listeners) 357 { 358 instance.listeners.remove(WorkspaceRepositoryLoaderListener.class, listener); 359 } 360 } 361 362 /** 363 * fire event 364 */ 365 private void fireEvent() 366 { 367 for (WorkspaceRepositoryLoaderListener listener : listeners 368 .getListeners(WorkspaceRepositoryLoaderListener.class)) 369 listener.workspaceRepositeryLoaderChanged(); 370 } 371 372}