1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.workbench.internal;
14 import java.lang.reflect.InvocationTargetException;
15 import java.net.InetSocketAddress;
16 import java.util.HashSet;
19 import org.eclipse.core.runtime.IProgressMonitor;
20 import org.eclipse.core.runtime.IStatus;
21 import org.eclipse.core.runtime.MultiStatus;
22 import org.eclipse.core.runtime.Status;
23 import org.eclipse.jface.action.IAction;
24 import org.eclipse.jface.dialogs.ProgressMonitorDialog;
25 import org.eclipse.jface.operation.IRunnableWithProgress;
26 import org.eclipse.swt.widgets.Display;
27 import org.eclipse.ui.IWorkbenchWindow;
28 import org.simantics.application.arguments.ApplicationUtils;
29 import org.simantics.application.arguments.IArguments;
30 import org.simantics.application.arguments.SimanticsArguments;
31 import org.simantics.db.ReadGraph;
32 import org.simantics.db.Resource;
33 import org.simantics.db.Session;
34 import org.simantics.db.common.request.ReadRequest;
35 import org.simantics.db.common.utils.NameUtils;
36 import org.simantics.db.exception.DatabaseException;
37 import org.simantics.db.layer0.util.SimanticsKeys;
38 import org.simantics.db.management.ISessionContext;
39 import org.simantics.db.management.discovery.InetAddressUtils;
40 import org.simantics.db.request.Read;
41 import org.simantics.project.IProject;
42 import org.simantics.project.ProjectKeys;
43 import org.simantics.project.ProjectUtil;
44 import org.simantics.project.exception.ProjectException;
45 import org.simantics.project.utils.GraphPathUtils;
46 import org.simantics.ui.db.SessionData;
47 import org.simantics.ui.db.SessionRestoreUtils;
48 import org.simantics.ui.internal.Activator;
49 import org.simantics.ui.workbench.action.ChooseActionRequest;
50 import org.simantics.utils.ui.ExceptionUtils;
51 import org.simantics.utils.ui.action.IPriorityAction;
52 import org.simantics.utils.ui.dialogs.ShowMessage;
54 public class Initializer implements Runnable {
56 private final IArguments args;
58 // private String defaultPerspectiveId;
61 * This will be !ok if something fatal for startup has happened.
63 private final IStatus status = Status.OK_STATUS;
65 private ISessionContext ctx;
67 private IProject project;
69 private Resource model;
71 private final IWorkbenchWindow window;
73 // private Resource experiment;
76 public Initializer(IArguments args, IWorkbenchWindow window) {
79 // this.defaultPerspectiveId = defaultPerspectiveId;
86 } catch (DatabaseException e) {
88 } catch (ProjectException e) {
93 public IStatus getStatus() {
97 public ISessionContext getSessionContext() {
101 public IProject getProject() {
105 public Resource getModel() {
109 public boolean perform() throws DatabaseException, ProjectException {
110 // Nothing further can be done if no server is specified
111 if (!args.contains(SimanticsArguments.SERVER))
114 // Try to connect to designated server and project.
115 // Use null local server location to indicate checkout
116 String server = args.get(SimanticsArguments.SERVER);
117 if(server.indexOf(':') == -1 && args.contains(SimanticsArguments.PORT)) {
118 server = server+":"+args.get(SimanticsArguments.PORT);
120 InetSocketAddress serverAddress = InetAddressUtils.parseUnresolved(server);
121 String[] projectPath = ApplicationUtils.decodePath(args.get(SimanticsArguments.PROJECT));
122 final SessionData data = new SessionData(null, serverAddress, projectPath);
124 final MultiStatus status = new MultiStatus(Activator.PLUGIN_ID, IStatus.OK, "Database session could not be initialized.", null);
125 // final ProgressMonitorDialog dialog = new ProgressMonitorDialog(null);
127 final ProgressMonitorDialog dialog = new ProgressMonitorDialog(null);
129 dialog.run(false, true, new IRunnableWithProgress() {
131 public void run(final IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
132 ctx = SessionRestoreUtils.restoreSession(status, monitor, data);
133 //ctx = sessionResult;
136 } catch (InvocationTargetException e) {
137 ExceptionUtils.logAndShowError(e);
138 } catch (InterruptedException e) {
139 ExceptionUtils.logAndShowError(e);
142 //IDiscoveryModel model =
145 // IDiscoveryData[] iData = ProjectPlugin.getWorkspace().getDiscoveryModel().getDataSources();
146 // for(int i = 0; i < iData.length; i++) {
147 // IDiscoveryData d = iData[i];
148 // if(d.getLabel().equals(IWorkspaceConstants.DIRECT_SERVERS_LABEL)) {
149 // ServerInfo serverInfo = new ServerInfo(d.getLabel(), serverAddress);
150 // ServerData serverData = new ServerData(null, serverInfo, null);
151 // IServerData[] iServerData = d.getServers();
153 // IServerData[] newServerData = new IServerData[iServerData.length+1];
156 // for(y = 0; y < iServerData.length; y++) {
157 // newServerData[y] = iServerData[y];
160 // newServerData[y] = serverData;
162 // d.setServers(newServerData);
163 // ProjectPlugin.getWorkspace().getDiscoveryModel().updateDataSource(d);
169 //status = sessionResult.status;
170 //if (!status.isOK()) {
175 // Its okay to start the workbench, it will just be reset as the
176 // connection failed.
180 // FIXME: COMPLETE HACK for simupedia
181 // Add a discovery service to get in touch
183 IDiscoveryModel discoveryModel = ProjectPlugin.getWorkspace().getDiscoveryModel();
184 File discoveryFile = ProjectPlugin.getDefault().getStateLocation().append("simupedia-discovery.txt").toFile();
185 FileWriter fw = null;
187 // Overwrite the file.
188 fw = new FileWriter(discoveryFile, false);
189 String serverLine = String.format("'%s' %s\n", data.getAddress().getHostName(), server);
190 fw.write(serverLine);
191 } catch (IOException e) {
194 FileUtils.uncheckedClose(fw);
197 // Add a non-persistent simupedia discovery
198 DiscoveryData d = new DiscoveryData(IDiscoveryType.REMOTE, "Simupedia", discoveryFile);
199 discoveryModel.addDataSource(d);
200 } catch (MalformedURLException e) {
201 // Should never happen.
206 // Initialize project
207 if (args.contains(SimanticsArguments.NEW_PROJECT)) {
208 throw new UnsupportedOperationException();
209 //project = newProject(ctx);
210 } else if (args.contains(SimanticsArguments.PROJECT)) {
211 project = loadProject(ctx, projectPath);
214 // Only proceed with model and experiment loading if a project was
215 // successfully created or loaded.
216 if (project != null) {
217 ctx.setHint(ProjectKeys.KEY_PROJECT, project);
218 ctx.setHint(SimanticsKeys.KEY_PROJECT, project.get());
221 if (args.contains(SimanticsArguments.NEW_MODEL)) {
222 //model = newModel(ctx.getSession(), project);
223 } else if (args.contains(SimanticsArguments.MODEL)) {
224 String[] modelPath = ApplicationUtils.decodePath(args.get(SimanticsArguments.MODEL));
225 model = findModel(ctx.getSession(), project, modelPath);
227 // if (model != null) {
228 // findDiagram(ctx.getSession(), model, project);
231 // TODO: load experiment
232 if (args.contains(SimanticsArguments.EXPERIMENT)) {
233 // String[] experimentPath = decodePath(args.get(ProConfArguments.EXPERIMENT));
240 IProject loadProject(ISessionContext ctx, final String[] projectNamePath) throws DatabaseException, ProjectException {
242 IProject project = ctx.getSession().syncRequest(new Read<IProject>() {
245 public IProject perform(ReadGraph graph) throws DatabaseException {
246 Resource projects = graph.getResource("http://Projects");
247 Resource[] path = GraphPathUtils.toResourcePath(graph, projects, projectNamePath, graph
248 .getBuiltins().ConsistsOf);
249 if (path.length == 0) {
250 IllegalArgumentException e = new IllegalArgumentException("");
251 ShowMessage.showError("Error loading the existing project", e.getMessage());
252 throw new DatabaseException(e);
254 return ProjectUtil.loadProject(graph, path[path.length - 1]);
263 // final GraphRequestWithResult<IProject> request = new GraphRequestWithResult<IProject>() {
265 // public IProject performWithResult(Graph g) throws Exception {
268 // ctx.getSession().syncRead(request);
269 // if (request.getException() != null) {
270 // ShowMessage.showError("Error loading the existing project", request.getException().getMessage());
273 // return request.getResult();
276 Resource findModel(final Session session, final IProject project, final String[] modelPath) throws DatabaseException {
278 return session.syncRequest(new Read<Resource>() {
281 public Resource perform(ReadGraph graph) throws DatabaseException {
282 Resource[] path = GraphPathUtils.toResourcePath(graph, project.get(), modelPath, graph
283 .getBuiltins().ConsistsOf);
284 if (path.length == 0) {
285 IllegalArgumentException e = new IllegalArgumentException("");
286 ShowMessage.showError("Error loading the existing project", e.getMessage());
287 throw new DatabaseException(e);
289 else return path[path.length - 1];
294 // final GraphRequestWithResult<Resource> request = new GraphRequestWithResult<Resource>() {
296 // public Resource performWithResult(Graph g) {
297 // Resource[] path = GraphPathUtils.toResourcePath(g, project.getResource(), modelPath,
298 // g.getBuiltins().ConsistsOf);
299 // if (path.length == 0)
300 // throw new IllegalArgumentException("");
301 // return path[path.length - 1];
304 // session.syncRead(request);
305 // if (request.getException() != null) {
306 // ShowMessage.showError("Error loading the existing project", request.getException().getMessage());
309 // return request.getResult();
312 final Set<String> reservedProjectNames = new HashSet<String>();
313 // IProject newProject(final ISessionContext ctx) throws DatabaseException {
314 // // ---------------------------------------------------------------------
315 // // Show the wizard to the user.
316 // final NewProjectModel2 model = ProjectWizardUtil.initializeNewProjectModel2(new NullProgressMonitor(), ctx);
317 // final NewProjectWizard2 wizard = new NewProjectWizard2(ctx.getSession(), model, null);
318 // int ok = new WizardDialog(null, wizard).open();
319 // if (ok != Window.OK) {
320 // // User cancelled the wizard.
324 // final DataContainer<IProject> project = new DataContainer<IProject>();
326 // ctx.getSession().syncRequest(new WriteRequest() {
329 // public void perform(WriteGraph g) {
333 // // TODO: add features
334 // System.out.println("TODO: add features to project");
335 // Collection<IProjectFeatureDescriptor> fds = Collections.emptyList();
336 // Resource res = ProjectUtil.createProject(g, model.projectName, fds);
337 // project.set(ProjectUtil.loadProject(g, res, false));
339 // } catch (Exception e) {
340 // ShowMessage.showError("Error creating new project", e.getMessage());
347 // return project.get();
352 Resource newModel(final Session session, final IProject project) {
353 final ISimulationProjectParticipant sim = project.getSingleParticipant(ISimulationProjectParticipant.class);
357 final Resource[] result = { null };
358 final Semaphore sem = new Semaphore(0);
359 findModelLibrary(session, project.getResource(), new RunnableWithParameter<Resource>() {
361 public void run(Resource modelLibrary) {
362 sim.createModel(modelLibrary,
363 new RunnableWithParameter<Resource>() {
365 public void run(Resource model) {
370 new RunnableWithParameter<Throwable>() {
372 public void run(Throwable e) {
373 ErrorLogger.defaultLogError("New model creation failed, see exception for details.", e);
379 new RunnableWithParameter<Throwable>() {
381 public void run(Throwable e) {
383 ErrorLogger.defaultLogError("New model creation failed, see exception for details.", e);
385 ErrorLogger.defaultLogError("New model creation failed, no model library found.", null);
390 // Wait until the model creation has finished or failed.
393 } catch (InterruptedException e) {
400 void findModelLibrary(Session session,
401 final Resource project,
402 final RunnableWithParameter<Resource> libraryAction,
403 final RunnableWithParameter<Throwable> errorCallback)
405 // TODO: all of this is not that generic, what is someone decices he/she
406 // doesn't want a model library called Models at the root of his/her
409 // If the new model consists of a single diagram, open it.
410 session.asyncRequest(new WriteRequest() {
412 public void perform(WriteGraph g) throws Exception {
413 Resource modelLibrary = null;
415 Builtins b = g.getBuiltins();
416 for (Resource r : g.getObjects2(project, b.ConsistsOf)) {
417 if (g.isInstanceOf2(r, b.ModelLibrary)) {
422 // FIXME: this is definitely project specific, not generic.
423 if (modelLibrary == null) {
424 modelLibrary = InstanceFactory.instantiate(g, b.ModelLibrary);
425 GraphUtils.addRelatedScalarString(g, modelLibrary, b.HasName, "Models");
426 g.claim(project, b.ConsistsOf, modelLibrary);
428 libraryAction.run(modelLibrary);
429 } catch (Exception e) {
430 errorCallback.run(e);
437 // void findDiagram(Session session, final Resource model, final IProject project) {
438 // // If the new model consists of a single diagram, open it.
439 // session.asyncRequest(new ReadRequest() {
441 // public void run(ReadGraph g) throws DatabaseException {
442 // Builtins b = g.getBuiltins();
443 // DiagramResource dr = DiagramResource.getInstance(g);
444 // for (Resource r : g.getObjects(model, b.ConsistsOf)) {
445 // if (g.isInstanceOf(r, dr.Diagram)) {
446 // String defaultPerspective = project.getHint(ProjectKeys.DEFAULT_PERSPECTIVE);
447 // openPreferredEditor(ctx.getSession(), r, defaultPerspective);
455 void openPreferredEditor(Session s, final Resource r, final String defaultPerspective) {
457 s.asyncRequest(new ReadRequest() {
460 public void run(ReadGraph g) throws DatabaseException {
461 final String resourceName = NameUtils.getSafeName(g, r);
462 final IPriorityAction[] actions = ChooseActionRequest.findActions(g, r, defaultPerspective);
465 Display.getDefault().asyncExec(new Runnable() {
468 IAction action = ChooseActionRequest.chooseAction(null, actions, resourceName);